mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1309030 - Remove DOM/identity and related code. r=Ehsan
MozReview-Commit-ID: 2v2ZCSoX4Mz --HG-- extra : rebase_source : 72cbccd1f59758e290294bfcca56523372978120
This commit is contained in:
parent
5fcdb45cbd
commit
6b31140392
@ -791,9 +791,6 @@ pref("memory.dump_reports_on_oom", false);
|
||||
pref("layout.framevisibility.numscrollportwidths", 1);
|
||||
pref("layout.framevisibility.numscrollportheights", 1);
|
||||
|
||||
// Enable native identity (persona/browserid)
|
||||
pref("dom.identity.enabled", true);
|
||||
|
||||
// Wait up to this much milliseconds when orientation changed
|
||||
pref("layers.orientation.sync.timeout", 1000);
|
||||
|
||||
@ -962,7 +959,7 @@ pref("layout.accessiblecaret.timeout_ms", 3000);
|
||||
// Hide carets and text selection dialog during scrolling.
|
||||
pref("layout.accessiblecaret.always_show_when_scrolling", false);
|
||||
|
||||
// Enable sync and mozId with Firefox Accounts.
|
||||
// Enable sync with Firefox Accounts.
|
||||
pref("services.sync.fxaccounts.enabled", true);
|
||||
pref("identity.fxaccounts.enabled", true);
|
||||
|
||||
|
@ -1,478 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc,
|
||||
interfaces: Ci,
|
||||
utils: Cu,
|
||||
results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const PREF_FXA_ENABLED = "identity.fxaccounts.enabled";
|
||||
const FXA_PERMISSION = "firefox-accounts";
|
||||
|
||||
// This is the parent process corresponding to nsDOMIdentity.
|
||||
this.EXPORTED_SYMBOLS = ["DOMIdentity"];
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
/* jshint ignore:start */
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
|
||||
#ifdef MOZ_B2G_VERSION
|
||||
"resource://gre/modules/identity/MinimalIdentity.jsm");
|
||||
#else
|
||||
"resource://gre/modules/identity/Identity.jsm");
|
||||
#endif
|
||||
/* jshint ignore:end */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FirefoxAccounts",
|
||||
"resource://gre/modules/identity/FirefoxAccounts.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
"Logger",
|
||||
"resource://gre/modules/identity/LogUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageListenerManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
|
||||
"@mozilla.org/permissionmanager;1",
|
||||
"nsIPermissionManager");
|
||||
|
||||
function log(...aMessageArgs) {
|
||||
Logger.log.apply(Logger, ["DOMIdentity"].concat(aMessageArgs));
|
||||
}
|
||||
|
||||
function IDDOMMessage(aOptions) {
|
||||
objectCopy(aOptions, this);
|
||||
}
|
||||
|
||||
function _sendAsyncMessage(identifier, message) {
|
||||
if (this._mm) {
|
||||
try {
|
||||
this._mm.sendAsyncMessage(identifier, message);
|
||||
} catch(err) {
|
||||
// We may receive a NS_ERROR_NOT_INITIALIZED if the target window has
|
||||
// been closed. This can legitimately happen if an app has been killed
|
||||
// while we are in the midst of a sign-in flow.
|
||||
if (err.result == Cr.NS_ERROR_NOT_INITIALIZED) {
|
||||
log("Cannot sendAsyncMessage because the recipient frame has closed");
|
||||
return;
|
||||
}
|
||||
log("ERROR: sendAsyncMessage: " + err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function IDPProvisioningContext(aID, aOrigin, aTargetMM) {
|
||||
this._id = aID;
|
||||
this._origin = aOrigin;
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
IDPProvisioningContext.prototype = {
|
||||
get id() { return this._id; },
|
||||
get origin() { return this._origin; },
|
||||
|
||||
sendAsyncMessage: _sendAsyncMessage,
|
||||
|
||||
doBeginProvisioningCallback: function IDPPC_doBeginProvCB(aID, aCertDuration) {
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.identity = aID;
|
||||
message.certDuration = aCertDuration;
|
||||
this.sendAsyncMessage("Identity:IDP:CallBeginProvisioningCallback",
|
||||
message);
|
||||
},
|
||||
|
||||
doGenKeyPairCallback: function IDPPC_doGenKeyPairCallback(aPublicKey) {
|
||||
log("doGenKeyPairCallback");
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.publicKey = aPublicKey;
|
||||
this.sendAsyncMessage("Identity:IDP:CallGenKeyPairCallback", message);
|
||||
},
|
||||
|
||||
doError: function(msg) {
|
||||
log("Provisioning ERROR: " + msg);
|
||||
}
|
||||
};
|
||||
|
||||
function IDPAuthenticationContext(aID, aOrigin, aTargetMM) {
|
||||
this._id = aID;
|
||||
this._origin = aOrigin;
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
IDPAuthenticationContext.prototype = {
|
||||
get id() { return this._id; },
|
||||
get origin() { return this._origin; },
|
||||
|
||||
sendAsyncMessage: _sendAsyncMessage,
|
||||
|
||||
doBeginAuthenticationCallback: function IDPAC_doBeginAuthCB(aIdentity) {
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.identity = aIdentity;
|
||||
this.sendAsyncMessage("Identity:IDP:CallBeginAuthenticationCallback",
|
||||
message);
|
||||
},
|
||||
|
||||
doError: function IDPAC_doError(msg) {
|
||||
log("Authentication ERROR: " + msg);
|
||||
}
|
||||
};
|
||||
|
||||
function RPWatchContext(aOptions, aTargetMM, aPrincipal) {
|
||||
objectCopy(aOptions, this);
|
||||
|
||||
// id and origin are required
|
||||
if (! (this.id && this.origin)) {
|
||||
throw new Error("id and origin are required for RP watch context");
|
||||
}
|
||||
|
||||
this.principal = aPrincipal;
|
||||
|
||||
// default for no loggedInUser is undefined, not null
|
||||
this.loggedInUser = aOptions.loggedInUser;
|
||||
|
||||
// Maybe internal. For hosted b2g identity shim.
|
||||
this._internal = aOptions._internal;
|
||||
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
RPWatchContext.prototype = {
|
||||
sendAsyncMessage: _sendAsyncMessage,
|
||||
|
||||
doLogin: function RPWatchContext_onlogin(aAssertion, aMaybeInternalParams) {
|
||||
log("doLogin: " + this.id);
|
||||
let message = new IDDOMMessage({id: this.id, assertion: aAssertion});
|
||||
if (aMaybeInternalParams) {
|
||||
message._internalParams = aMaybeInternalParams;
|
||||
}
|
||||
this.sendAsyncMessage("Identity:RP:Watch:OnLogin", message);
|
||||
},
|
||||
|
||||
doLogout: function RPWatchContext_onlogout() {
|
||||
log("doLogout: " + this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
this.sendAsyncMessage("Identity:RP:Watch:OnLogout", message);
|
||||
},
|
||||
|
||||
doReady: function RPWatchContext_onready() {
|
||||
log("doReady: " + this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
this.sendAsyncMessage("Identity:RP:Watch:OnReady", message);
|
||||
},
|
||||
|
||||
doCancel: function RPWatchContext_oncancel() {
|
||||
log("doCancel: " + this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
this.sendAsyncMessage("Identity:RP:Watch:OnCancel", message);
|
||||
},
|
||||
|
||||
doError: function RPWatchContext_onerror(aMessage) {
|
||||
log("doError: " + this.id + ": " + JSON.stringify(aMessage));
|
||||
let message = new IDDOMMessage({id: this.id, message: aMessage});
|
||||
this.sendAsyncMessage("Identity:RP:Watch:OnError", message);
|
||||
}
|
||||
};
|
||||
|
||||
this.DOMIdentity = {
|
||||
/*
|
||||
* When relying parties (RPs) invoke the watch() method, they can request
|
||||
* to use Firefox Accounts as their auth service or BrowserID (the default).
|
||||
* For each RP, we create an RPWatchContext to store the parameters given to
|
||||
* watch(), and to provide hooks to invoke the onlogin(), onlogout(), etc.
|
||||
* callbacks held in the nsDOMIdentity state.
|
||||
*
|
||||
* The serviceContexts map associates the window ID of the RP with the
|
||||
* context object. The mmContexts map associates a message manager with a
|
||||
* window ID. We use the mmContexts map when child-process-shutdown is
|
||||
* observed, and all we have is a message manager to identify the window in
|
||||
* question.
|
||||
*/
|
||||
_serviceContexts: new Map(),
|
||||
_mmContexts: new Map(),
|
||||
|
||||
/*
|
||||
* Mockable, for testing
|
||||
*/
|
||||
_mockIdentityService: null,
|
||||
get IdentityService() {
|
||||
if (this._mockIdentityService) {
|
||||
log("Using a mocked identity service");
|
||||
return this._mockIdentityService;
|
||||
}
|
||||
return IdentityService;
|
||||
},
|
||||
|
||||
/*
|
||||
* Create a new RPWatchContext, and update the context maps.
|
||||
*/
|
||||
newContext: function(message, targetMM, principal) {
|
||||
let context = new RPWatchContext(message, targetMM, principal);
|
||||
this._serviceContexts.set(message.id, context);
|
||||
this._mmContexts.set(targetMM, message.id);
|
||||
return context;
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the identity service used for an RP.
|
||||
*
|
||||
* @object message
|
||||
* A message received from an RP. Will include the id of the window
|
||||
* whence the message originated.
|
||||
*
|
||||
* Returns FirefoxAccounts or IdentityService
|
||||
*/
|
||||
getService: function(message) {
|
||||
if (!this._serviceContexts.has(message.id)) {
|
||||
log("ERROR: getService called before newContext for " + message.id);
|
||||
return null;
|
||||
}
|
||||
|
||||
let context = this._serviceContexts.get(message.id);
|
||||
if (context.wantIssuer == "firefox-accounts") {
|
||||
if (Services.prefs.getPrefType(PREF_FXA_ENABLED) === Ci.nsIPrefBranch.PREF_BOOL
|
||||
&& Services.prefs.getBoolPref(PREF_FXA_ENABLED)) {
|
||||
return FirefoxAccounts;
|
||||
}
|
||||
log("WARNING: Firefox Accounts is not enabled; Defaulting to BrowserID");
|
||||
}
|
||||
return this.IdentityService;
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the RPWatchContext object for a given message manager.
|
||||
*/
|
||||
getContextForMM: function(targetMM) {
|
||||
return this._serviceContexts.get(this._mmContexts.get(targetMM));
|
||||
},
|
||||
|
||||
hasContextForMM: function(targetMM) {
|
||||
return this._mmContexts.has(targetMM);
|
||||
},
|
||||
|
||||
/*
|
||||
* Delete the RPWatchContext object for a given message manager. Removes the
|
||||
* mapping both from _serviceContexts and _mmContexts.
|
||||
*/
|
||||
deleteContextForMM: function(targetMM) {
|
||||
this._serviceContexts.delete(this._mmContexts.get(targetMM));
|
||||
this._mmContexts.delete(targetMM);
|
||||
},
|
||||
|
||||
hasPermission: function(aMessage) {
|
||||
// We only check that the firefox accounts permission is present in the
|
||||
// manifest.
|
||||
if (aMessage.json && aMessage.json.wantIssuer == "firefox-accounts") {
|
||||
if (!aMessage.principal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let permission =
|
||||
permissionManager.testPermissionFromPrincipal(aMessage.principal,
|
||||
FXA_PERMISSION);
|
||||
return permission != Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
permission != Ci.nsIPermissionManager.DENY_ACTION;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// nsIMessageListener
|
||||
receiveMessage: function DOMIdentity_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
|
||||
// Target is the frame message manager that called us and is
|
||||
// used to send replies back to the proper window.
|
||||
let targetMM = aMessage.target;
|
||||
|
||||
if (!this.hasPermission(aMessage)) {
|
||||
throw new Error("PERMISSION_DENIED");
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
// RP
|
||||
case "Identity:RP:Watch":
|
||||
this._watch(msg, targetMM, aMessage.principal);
|
||||
break;
|
||||
case "Identity:RP:Unwatch":
|
||||
this._unwatch(msg, targetMM);
|
||||
break;
|
||||
case "Identity:RP:Request":
|
||||
this._request(msg);
|
||||
break;
|
||||
case "Identity:RP:Logout":
|
||||
this._logout(msg);
|
||||
break;
|
||||
// IDP
|
||||
case "Identity:IDP:BeginProvisioning":
|
||||
this._beginProvisioning(msg, targetMM);
|
||||
break;
|
||||
case "Identity:IDP:GenKeyPair":
|
||||
this._genKeyPair(msg);
|
||||
break;
|
||||
case "Identity:IDP:RegisterCertificate":
|
||||
this._registerCertificate(msg);
|
||||
break;
|
||||
case "Identity:IDP:ProvisioningFailure":
|
||||
this._provisioningFailure(msg);
|
||||
break;
|
||||
case "Identity:IDP:BeginAuthentication":
|
||||
this._beginAuthentication(msg, targetMM);
|
||||
break;
|
||||
case "Identity:IDP:CompleteAuthentication":
|
||||
this._completeAuthentication(msg);
|
||||
break;
|
||||
case "Identity:IDP:AuthenticationFailure":
|
||||
this._authenticationFailure(msg);
|
||||
break;
|
||||
case "child-process-shutdown":
|
||||
// we receive child-process-shutdown if the appliction crashes,
|
||||
// including if it is crashed by the OS (killed for out-of-memory,
|
||||
// for example)
|
||||
this._childProcessShutdown(targetMM);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function DOMIdentity_observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "xpcom-shutdown":
|
||||
this._unsubscribeListeners();
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.ww.unregisterNotification(this);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
messages: ["Identity:RP:Watch", "Identity:RP:Request", "Identity:RP:Logout",
|
||||
"Identity:IDP:BeginProvisioning", "Identity:IDP:ProvisioningFailure",
|
||||
"Identity:IDP:RegisterCertificate", "Identity:IDP:GenKeyPair",
|
||||
"Identity:IDP:BeginAuthentication",
|
||||
"Identity:IDP:CompleteAuthentication",
|
||||
"Identity:IDP:AuthenticationFailure",
|
||||
"Identity:RP:Unwatch",
|
||||
"child-process-shutdown"],
|
||||
|
||||
// Private.
|
||||
_init: function DOMIdentity__init() {
|
||||
Services.ww.registerNotification(this);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
this._subscribeListeners();
|
||||
},
|
||||
|
||||
_subscribeListeners: function DOMIdentity__subscribeListeners() {
|
||||
if (!ppmm) {
|
||||
return;
|
||||
}
|
||||
for (let message of this.messages) {
|
||||
ppmm.addMessageListener(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
_unsubscribeListeners: function DOMIdentity__unsubscribeListeners() {
|
||||
for (let message of this.messages) {
|
||||
ppmm.removeMessageListener(message, this);
|
||||
}
|
||||
ppmm = null;
|
||||
},
|
||||
|
||||
_watch: function DOMIdentity__watch(message, targetMM, principal) {
|
||||
log("DOMIdentity__watch: " + message.id + " - " + principal);
|
||||
let context = this.newContext(message, targetMM, principal);
|
||||
this.getService(message).RP.watch(context);
|
||||
},
|
||||
|
||||
_unwatch: function DOMIdentity_unwatch(message, targetMM) {
|
||||
log("DOMIDentity__unwatch: " + message.id);
|
||||
// If watch failed for some reason (e.g., exception thrown because RP did
|
||||
// not have the right callbacks, we don't want unwatch to throw, because it
|
||||
// will break the process of releasing the page's resources and leak
|
||||
// memory.
|
||||
let service = this.getService(message);
|
||||
if (service && service.RP) {
|
||||
service.RP.unwatch(message.id, targetMM);
|
||||
this.deleteContextForMM(targetMM);
|
||||
return;
|
||||
}
|
||||
log("Can't find a service to unwatch() for " + message.id);
|
||||
},
|
||||
|
||||
_request: function DOMIdentity__request(message) {
|
||||
let service = this.getService(message);
|
||||
if (service && service.RP) {
|
||||
service.RP.request(message.id, message);
|
||||
return;
|
||||
}
|
||||
log("No context in which to call request(); Did you call watch() first?");
|
||||
},
|
||||
|
||||
_logout: function DOMIdentity__logout(message) {
|
||||
let service = this.getService(message);
|
||||
if (service && service.RP) {
|
||||
service.RP.logout(message.id, message.origin, message);
|
||||
return;
|
||||
}
|
||||
log("No context in which to call logout(); Did you call watch() first?");
|
||||
},
|
||||
|
||||
_childProcessShutdown: function DOMIdentity__childProcessShutdown(targetMM) {
|
||||
if (!this.hasContextForMM(targetMM)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let service = this.getContextForMM(targetMM);
|
||||
if (service && service.RP) {
|
||||
service.RP.childProcessShutdown(targetMM);
|
||||
}
|
||||
|
||||
this.deleteContextForMM(targetMM);
|
||||
|
||||
let options = makeMessageObject({messageManager: targetMM, id: null, origin: null});
|
||||
Services.obs.notifyObservers({wrappedJSObject: options}, "identity-child-process-shutdown", null);
|
||||
},
|
||||
|
||||
_beginProvisioning: function DOMIdentity__beginProvisioning(message, targetMM) {
|
||||
let context = new IDPProvisioningContext(message.id, message.origin,
|
||||
targetMM);
|
||||
this.getService(message).IDP.beginProvisioning(context);
|
||||
},
|
||||
|
||||
_genKeyPair: function DOMIdentity__genKeyPair(message) {
|
||||
this.getService(message).IDP.genKeyPair(message.id);
|
||||
},
|
||||
|
||||
_registerCertificate: function DOMIdentity__registerCertificate(message) {
|
||||
this.getService(message).IDP.registerCertificate(message.id, message.cert);
|
||||
},
|
||||
|
||||
_provisioningFailure: function DOMIdentity__provisioningFailure(message) {
|
||||
this.getService(message).IDP.raiseProvisioningFailure(message.id, message.reason);
|
||||
},
|
||||
|
||||
_beginAuthentication: function DOMIdentity__beginAuthentication(message, targetMM) {
|
||||
let context = new IDPAuthenticationContext(message.id, message.origin,
|
||||
targetMM);
|
||||
this.getService(message).IDP.beginAuthentication(context);
|
||||
},
|
||||
|
||||
_completeAuthentication: function DOMIdentity__completeAuthentication(message) {
|
||||
this.getService(message).IDP.completeAuthentication(message.id);
|
||||
},
|
||||
|
||||
_authenticationFailure: function DOMIdentity__authenticationFailure(message) {
|
||||
this.getService(message).IDP.cancelAuthentication(message.id);
|
||||
}
|
||||
};
|
||||
|
||||
// Object is initialized by nsIDService.js
|
@ -1,8 +0,0 @@
|
||||
# nsDOMIdentity.js
|
||||
component {210853d9-2c97-4669-9761-b1ab9cbf57ef} nsDOMIdentity.js
|
||||
contract @mozilla.org/identity/manager;1 {210853d9-2c97-4669-9761-b1ab9cbf57ef}
|
||||
|
||||
# nsIDService.js (initialization on startup)
|
||||
component {4e0a0e98-b1d3-4745-a1eb-f815199dd06b} nsIDService.js
|
||||
contract @mozilla.org/dom/identity/service;1 {4e0a0e98-b1d3-4745-a1eb-f815199dd06b}
|
||||
category app-startup IDService @mozilla.org/dom/identity/service;1
|
@ -1,17 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'Identity.manifest',
|
||||
'nsDOMIdentity.js',
|
||||
'nsIDService.js',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'DOMIdentity.jsm',
|
||||
]
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
|
@ -1,800 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const PREF_DEBUG = "toolkit.identity.debug";
|
||||
const PREF_ENABLED = "dom.identity.enabled";
|
||||
|
||||
// Bug 822450: Workaround for Bug 821740. When testing with marionette,
|
||||
// relax navigator.id.request's requirement that it be handling native
|
||||
// events. Synthetic marionette events are ok.
|
||||
const PREF_SYNTHETIC_EVENTS_OK = "dom.identity.syntheticEventsOk";
|
||||
|
||||
// Maximum length of a string that will go through IPC
|
||||
const MAX_STRING_LENGTH = 2048;
|
||||
// Maximum number of times navigator.id.request can be called for a document
|
||||
const MAX_RP_CALLS = 100;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "checkDeprecated",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "checkRenamed",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
// This is the child process corresponding to nsIDOMIdentity
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
|
||||
const ERRORS = {
|
||||
"ERROR_INVALID_ASSERTION_AUDIENCE":
|
||||
"Assertion audience may not differ from origin",
|
||||
"ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT":
|
||||
"The request() method may only be invoked when handling user input",
|
||||
};
|
||||
|
||||
function nsDOMIdentity() {
|
||||
}
|
||||
|
||||
nsDOMIdentity.prototype = {
|
||||
|
||||
// require native events unless syntheticEventsOk is set
|
||||
get nativeEventsRequired() {
|
||||
if (Services.prefs.prefHasUserValue(PREF_SYNTHETIC_EVENTS_OK) &&
|
||||
(Services.prefs.getPrefType(PREF_SYNTHETIC_EVENTS_OK) ===
|
||||
Ci.nsIPrefBranch.PREF_BOOL)) {
|
||||
return !Services.prefs.getBoolPref(PREF_SYNTHETIC_EVENTS_OK);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
reportErrors: function(message) {
|
||||
let onerror = function() {};
|
||||
if (this._rpWatcher && this._rpWatcher.onerror) {
|
||||
onerror = this._rpWatcher.onerror;
|
||||
}
|
||||
|
||||
message.errors.forEach((error) => {
|
||||
// Report an error string to content
|
||||
Cu.reportError(ERRORS[error]);
|
||||
|
||||
// Report error code to RP callback, if available
|
||||
onerror(error);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Relying Party (RP) APIs
|
||||
*/
|
||||
|
||||
watch: function nsDOMIdentity_watch(aOptions = {}) {
|
||||
aOptions = Cu.waiveXrays(aOptions);
|
||||
if (this._rpWatcher) {
|
||||
// For the initial release of Firefox Accounts, we support callers who
|
||||
// invoke watch() either for Firefox Accounts, or Persona, but not both.
|
||||
// In the future, we may wish to support the dual invocation (say, for
|
||||
// packaged apps so they can sign users in who reject the app's request
|
||||
// to sign in with their Firefox Accounts identity).
|
||||
throw new Error("navigator.id.watch was already called");
|
||||
}
|
||||
|
||||
assertCorrectCallbacks(aOptions);
|
||||
|
||||
let message = this.DOMIdentityMessage(aOptions);
|
||||
|
||||
// loggedInUser vs loggedInEmail
|
||||
// https://developer.mozilla.org/en-US/docs/DOM/navigator.id.watch
|
||||
// This parameter, loggedInUser, was renamed from loggedInEmail in early
|
||||
// September, 2012. Both names will continue to work for the time being,
|
||||
// but code should be changed to use loggedInUser instead.
|
||||
checkRenamed(aOptions, "loggedInEmail", "loggedInUser");
|
||||
|
||||
// Bad IPC or IDL converts null and undefined to "null" and "undefined".
|
||||
// We can't assign to aOptions, which complicates the workaround.
|
||||
message["loggedInUser"] = aOptions["loggedInUser"];
|
||||
if (message.loggedInUser == "null" || message.loggedInUser == "undefined") {
|
||||
message.loggedInUser = null;
|
||||
}
|
||||
|
||||
if (message.loggedInUser) {
|
||||
if (typeof(message.loggedInUser) !== "string") {
|
||||
throw new Error("loggedInUser must be a String or null");
|
||||
}
|
||||
|
||||
// TODO: Bug 767610 - check email format.
|
||||
// See HTMLInputElement::IsValidEmailAddress
|
||||
if (aOptions["loggedInUser"].indexOf("@") == -1
|
||||
|| aOptions["loggedInUser"].length > MAX_STRING_LENGTH) {
|
||||
throw new Error("loggedInUser is not valid");
|
||||
}
|
||||
}
|
||||
this._log("loggedInUser: " + message.loggedInUser);
|
||||
|
||||
this._rpWatcher = aOptions;
|
||||
this._rpWatcher.audience = message.audience;
|
||||
|
||||
if (message.errors.length) {
|
||||
this.reportErrors(message);
|
||||
// We don't delete the rpWatcher object, because we don't want the
|
||||
// broken client to be able to call watch() any more. It's broken.
|
||||
return;
|
||||
}
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:RP:Watch",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
request: function nsDOMIdentity_request(aOptions = {}) {
|
||||
aOptions = Cu.waiveXrays(aOptions);
|
||||
this._log("request: " + JSON.stringify(aOptions));
|
||||
|
||||
// Has the caller called watch() before this?
|
||||
if (!this._rpWatcher) {
|
||||
throw new Error("navigator.id.request called before navigator.id.watch");
|
||||
}
|
||||
if (this._rpCalls > MAX_RP_CALLS) {
|
||||
throw new Error("navigator.id.request called too many times");
|
||||
}
|
||||
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let message = this.DOMIdentityMessage(aOptions);
|
||||
|
||||
// We permit calling of request() outside of a user input handler only when
|
||||
// a certified or privileged app is calling, or when we are handling the
|
||||
// (deprecated) get() or getVerifiedEmail() calls, which make use of an RP
|
||||
// context marked as _internal.
|
||||
|
||||
if (!aOptions._internal &&
|
||||
this._appStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED &&
|
||||
this._appStatus !== Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
|
||||
|
||||
// If the caller is not special in one of those ways, see if the user has
|
||||
// preffed on 'syntheticEventsOk' (useful for testing); otherwise, if
|
||||
// this is a non-native event, reject it.
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
if (!util.isHandlingUserInput && this.nativeEventsRequired) {
|
||||
message.errors.push("ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT");
|
||||
}
|
||||
}
|
||||
|
||||
// Report and fail hard on any errors.
|
||||
if (message.errors.length) {
|
||||
this.reportErrors(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOptions) {
|
||||
// Optional string properties
|
||||
let optionalStringProps = ["privacyPolicy", "termsOfService"];
|
||||
for (let propName of optionalStringProps) {
|
||||
if (!aOptions[propName] || aOptions[propName] === "undefined")
|
||||
continue;
|
||||
if (typeof(aOptions[propName]) !== "string") {
|
||||
throw new Error(propName + " must be a string representing a URL.");
|
||||
}
|
||||
if (aOptions[propName].length > MAX_STRING_LENGTH) {
|
||||
throw new Error(propName + " is invalid.");
|
||||
}
|
||||
message[propName] = aOptions[propName];
|
||||
}
|
||||
|
||||
if (aOptions["oncancel"]
|
||||
&& typeof(aOptions["oncancel"]) !== "function") {
|
||||
throw new Error("oncancel is not a function");
|
||||
} else {
|
||||
// Store optional cancel callback for later.
|
||||
this._onCancelRequestCallback = aOptions.oncancel;
|
||||
}
|
||||
}
|
||||
|
||||
this._rpCalls++;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:RP:Request",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
logout: function nsDOMIdentity_logout() {
|
||||
if (!this._rpWatcher) {
|
||||
throw new Error("navigator.id.logout called before navigator.id.watch");
|
||||
}
|
||||
if (this._rpCalls > MAX_RP_CALLS) {
|
||||
throw new Error("navigator.id.logout called too many times");
|
||||
}
|
||||
|
||||
this._rpCalls++;
|
||||
let message = this.DOMIdentityMessage();
|
||||
|
||||
// Report and fail hard on any errors.
|
||||
if (message.errors.length) {
|
||||
this.reportErrors(message);
|
||||
return;
|
||||
}
|
||||
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:RP:Logout",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
/*
|
||||
* Get an assertion. This function is deprecated. RPs are
|
||||
* encouraged to use the observer API instead (watch + request).
|
||||
*/
|
||||
get: function nsDOMIdentity_get(aCallback, aOptions) {
|
||||
var opts = {};
|
||||
aOptions = aOptions || {};
|
||||
|
||||
// We use the observer API (watch + request) to implement get().
|
||||
// Because the caller can call get() and getVerifiedEmail() as
|
||||
// many times as they want, we lift the restriction that watch() can
|
||||
// only be called once.
|
||||
this._rpWatcher = null;
|
||||
|
||||
// This flag tells internal_api.js (in the shim) to record in the
|
||||
// login parameters whether the assertion was acquired silently or
|
||||
// with user interaction.
|
||||
opts._internal = true;
|
||||
|
||||
opts.privacyPolicy = aOptions.privacyPolicy || undefined;
|
||||
opts.termsOfService = aOptions.termsOfService || undefined;
|
||||
opts.privacyURL = aOptions.privacyURL || undefined;
|
||||
opts.tosURL = aOptions.tosURL || undefined;
|
||||
opts.siteName = aOptions.siteName || undefined;
|
||||
opts.siteLogo = aOptions.siteLogo || undefined;
|
||||
|
||||
opts.oncancel = function get_oncancel() {
|
||||
if (aCallback) {
|
||||
aCallback(null);
|
||||
aCallback = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (checkDeprecated(aOptions, "silent")) {
|
||||
// Silent has been deprecated, do nothing. Placing the check here
|
||||
// prevents the callback from being called twice, once with null and
|
||||
// once after internalWatch has been called. See issue #1532:
|
||||
// https://github.com/mozilla/browserid/issues/1532
|
||||
if (aCallback) {
|
||||
setTimeout(function() { aCallback(null); }, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get an assertion by using our observer api: watch + request.
|
||||
var self = this;
|
||||
this.watch({
|
||||
_internal: true,
|
||||
onlogin: function get_onlogin(assertion, internalParams) {
|
||||
if (assertion && aCallback && internalParams && !internalParams.silent) {
|
||||
aCallback(assertion);
|
||||
aCallback = null;
|
||||
}
|
||||
},
|
||||
onlogout: function get_onlogout() {},
|
||||
onready: function get_onready() {
|
||||
self.request(opts);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getVerifiedEmail: function nsDOMIdentity_getVerifiedEmail(aCallback) {
|
||||
Cu.reportError("WARNING: getVerifiedEmail has been deprecated");
|
||||
this.get(aCallback, {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Identity Provider (IDP) Provisioning APIs
|
||||
*/
|
||||
|
||||
beginProvisioning: function nsDOMIdentity_beginProvisioning(aCallback) {
|
||||
this._log("beginProvisioning");
|
||||
if (this._beginProvisioningCallback) {
|
||||
throw new Error("navigator.id.beginProvisioning already called.");
|
||||
}
|
||||
if (!aCallback || typeof(aCallback) !== "function") {
|
||||
throw new Error("beginProvisioning callback is required.");
|
||||
}
|
||||
|
||||
this._beginProvisioningCallback = aCallback;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:BeginProvisioning",
|
||||
this.DOMIdentityMessage(),
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
genKeyPair: function nsDOMIdentity_genKeyPair(aCallback) {
|
||||
this._log("genKeyPair");
|
||||
if (!this._beginProvisioningCallback) {
|
||||
throw new Error("navigator.id.genKeyPair called outside of provisioning");
|
||||
}
|
||||
if (this._genKeyPairCallback) {
|
||||
throw new Error("navigator.id.genKeyPair already called.");
|
||||
}
|
||||
if (!aCallback || typeof(aCallback) !== "function") {
|
||||
throw new Error("genKeyPair callback is required.");
|
||||
}
|
||||
|
||||
this._genKeyPairCallback = aCallback;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:GenKeyPair",
|
||||
this.DOMIdentityMessage(),
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
registerCertificate: function nsDOMIdentity_registerCertificate(aCertificate) {
|
||||
this._log("registerCertificate");
|
||||
if (!this._genKeyPairCallback) {
|
||||
throw new Error("navigator.id.registerCertificate called outside of provisioning");
|
||||
}
|
||||
if (this._provisioningEnded) {
|
||||
throw new Error("Provisioning already ended");
|
||||
}
|
||||
this._provisioningEnded = true;
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.cert = aCertificate;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:RegisterCertificate",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
raiseProvisioningFailure: function nsDOMIdentity_raiseProvisioningFailure(aReason) {
|
||||
this._log("raiseProvisioningFailure '" + aReason + "'");
|
||||
if (this._provisioningEnded) {
|
||||
throw new Error("Provisioning already ended");
|
||||
}
|
||||
if (!aReason || typeof(aReason) != "string") {
|
||||
throw new Error("raiseProvisioningFailure reason is required");
|
||||
}
|
||||
this._provisioningEnded = true;
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.reason = aReason;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:ProvisioningFailure",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Identity Provider (IDP) Authentication APIs
|
||||
*/
|
||||
|
||||
beginAuthentication: function nsDOMIdentity_beginAuthentication(aCallback) {
|
||||
this._log("beginAuthentication");
|
||||
if (this._beginAuthenticationCallback) {
|
||||
throw new Error("navigator.id.beginAuthentication already called.");
|
||||
}
|
||||
if (typeof(aCallback) !== "function") {
|
||||
throw new Error("beginAuthentication callback is required.");
|
||||
}
|
||||
if (!aCallback || typeof(aCallback) !== "function") {
|
||||
throw new Error("beginAuthentication callback is required.");
|
||||
}
|
||||
|
||||
this._beginAuthenticationCallback = aCallback;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:BeginAuthentication",
|
||||
this.DOMIdentityMessage(),
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
completeAuthentication: function nsDOMIdentity_completeAuthentication() {
|
||||
if (this._authenticationEnded) {
|
||||
throw new Error("Authentication already ended");
|
||||
}
|
||||
if (!this._beginAuthenticationCallback) {
|
||||
throw new Error("navigator.id.completeAuthentication called outside of authentication");
|
||||
}
|
||||
this._authenticationEnded = true;
|
||||
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:CompleteAuthentication",
|
||||
this.DOMIdentityMessage(),
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
raiseAuthenticationFailure: function nsDOMIdentity_raiseAuthenticationFailure(aReason) {
|
||||
if (this._authenticationEnded) {
|
||||
throw new Error("Authentication already ended");
|
||||
}
|
||||
if (!aReason || typeof(aReason) != "string") {
|
||||
throw new Error("raiseProvisioningFailure reason is required");
|
||||
}
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.reason = aReason;
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:IDP:AuthenticationFailure",
|
||||
message,
|
||||
null,
|
||||
this._window.document.nodePrincipal
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called during init and shutdown.
|
||||
*/
|
||||
_initializeState: function nsDOMIdentity__initializeState() {
|
||||
// Some state to prevent abuse
|
||||
// Limit the number of calls to .request
|
||||
this._rpCalls = 0;
|
||||
this._provisioningEnded = false;
|
||||
this._authenticationEnded = false;
|
||||
|
||||
this._rpWatcher = null;
|
||||
this._onCancelRequestCallback = null;
|
||||
this._beginProvisioningCallback = null;
|
||||
this._genKeyPairCallback = null;
|
||||
this._beginAuthenticationCallback = null;
|
||||
},
|
||||
|
||||
// nsIMessageListener
|
||||
receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
|
||||
// Is this message intended for this window?
|
||||
if (msg.id != this._id) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Identity:ResetState":
|
||||
if (!this._debug) {
|
||||
return;
|
||||
}
|
||||
this._initializeState();
|
||||
Services.obs.notifyObservers(null, "identity-DOM-state-reset", this._id);
|
||||
break;
|
||||
case "Identity:RP:Watch:OnLogin":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
this._log("WARNING: Received OnLogin message, but there is no RP watcher");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onlogin) {
|
||||
if (this._rpWatcher._internal) {
|
||||
this._rpWatcher.onlogin(msg.assertion, msg._internalParams);
|
||||
} else {
|
||||
this._rpWatcher.onlogin(msg.assertion);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnLogout":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
this._log("WARNING: Received OnLogout message, but there is no RP watcher");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onlogout) {
|
||||
this._rpWatcher.onlogout();
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnReady":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
this._log("WARNING: Received OnReady message, but there is no RP watcher");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onready) {
|
||||
this._rpWatcher.onready();
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnCancel":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
this._log("WARNING: Received OnCancel message, but there is no RP " +
|
||||
"watcher");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._onCancelRequestCallback) {
|
||||
this._onCancelRequestCallback();
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnError":
|
||||
if (!this._rpWatcher) {
|
||||
this._log("WARNING: Received OnError message, but there is no RP " +
|
||||
"watcher");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onerror) {
|
||||
this._rpWatcher.onerror(JSON.stringify({name: msg.message.error}));
|
||||
}
|
||||
break;
|
||||
case "Identity:IDP:CallBeginProvisioningCallback":
|
||||
this._callBeginProvisioningCallback(msg);
|
||||
break;
|
||||
case "Identity:IDP:CallGenKeyPairCallback":
|
||||
this._callGenKeyPairCallback(msg);
|
||||
break;
|
||||
case "Identity:IDP:CallBeginAuthenticationCallback":
|
||||
this._callBeginAuthenticationCallback(msg);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_callGenKeyPairCallback: function nsDOMIdentity__callGenKeyPairCallback(message) {
|
||||
// create a pubkey object that works
|
||||
let chrome_pubkey = JSON.parse(message.publicKey);
|
||||
|
||||
// bunch of stuff to create a proper object in window context
|
||||
function genPropDesc(value) {
|
||||
return {
|
||||
enumerable: true, configurable: true, writable: true, value: value
|
||||
};
|
||||
}
|
||||
|
||||
let propList = {};
|
||||
for (let k in chrome_pubkey) {
|
||||
propList[k] = genPropDesc(chrome_pubkey[k]);
|
||||
}
|
||||
|
||||
let pubkey = Cu.createObjectIn(this._window);
|
||||
Object.defineProperties(pubkey, propList);
|
||||
Cu.makeObjectPropsNormal(pubkey);
|
||||
|
||||
// do the callback
|
||||
this._genKeyPairCallback(pubkey);
|
||||
},
|
||||
|
||||
_callBeginProvisioningCallback:
|
||||
function nsDOMIdentity__callBeginProvisioningCallback(message) {
|
||||
let identity = message.identity;
|
||||
let certValidityDuration = message.certDuration;
|
||||
this._beginProvisioningCallback(identity,
|
||||
certValidityDuration);
|
||||
},
|
||||
|
||||
_callBeginAuthenticationCallback:
|
||||
function nsDOMIdentity__callBeginAuthenticationCallback(message) {
|
||||
let identity = message.identity;
|
||||
this._beginAuthenticationCallback(identity);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to create messages to send using a message manager.
|
||||
* Pass through user options if they are not functions. Always
|
||||
* overwrite id, origin, audience, and appStatus. The caller
|
||||
* does not get to set those.
|
||||
*/
|
||||
DOMIdentityMessage: function DOMIdentityMessage(aOptions) {
|
||||
aOptions = aOptions || {};
|
||||
let message = {
|
||||
errors: []
|
||||
};
|
||||
|
||||
objectCopy(aOptions, message);
|
||||
|
||||
// outer window id
|
||||
message.id = this._id;
|
||||
|
||||
// window origin
|
||||
message.origin = this._origin;
|
||||
|
||||
// Normally the window origin will be the audience in assertions. On b2g,
|
||||
// certified apps have the power to override this and declare any audience
|
||||
// the want. Privileged apps can also declare a different audience, as
|
||||
// long as it is the same as the origin specified in their manifest files.
|
||||
// All other apps are stuck with b2g origins of the form app://{guid}.
|
||||
// Since such an origin is meaningless for the purposes of verification,
|
||||
// they will have to jump through some hoops to sign in: Specifically, they
|
||||
// will have to host their sign-in flows and DOM API requests in an iframe,
|
||||
// have the iframe xhr post assertions up to their server for verification,
|
||||
// and then post-message the results down to their app.
|
||||
let _audience = message.origin;
|
||||
if (message.audience && message.audience != message.origin) {
|
||||
if (this._appStatus === Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
_audience = message.audience;
|
||||
this._log("Certified app setting assertion audience: " + _audience);
|
||||
} else {
|
||||
message.errors.push("ERROR_INVALID_ASSERTION_AUDIENCE");
|
||||
}
|
||||
}
|
||||
|
||||
// Replace any audience supplied by the RP with one that has been sanitised
|
||||
message.audience = _audience;
|
||||
|
||||
this._log("DOMIdentityMessage: " + JSON.stringify(message));
|
||||
|
||||
return makeMessageObject(message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal methods that are not exposed to content.
|
||||
* See dom/webidl/Identity.webidl for the public interface.
|
||||
*/
|
||||
// nsIObserver
|
||||
observe: function nsDOMIdentityInternal_observe(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId != this._innerWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.uninit();
|
||||
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._initializeState();
|
||||
|
||||
// TODO: Also send message to DOMIdentity notifiying window is no longer valid
|
||||
// ie. in the case that the user closes the auth. window and we need to know.
|
||||
|
||||
try {
|
||||
for (let msgName of this._messages) {
|
||||
this._mm.removeMessageListener(msgName, this);
|
||||
}
|
||||
} catch (ex) {
|
||||
// Avoid errors when removing more than once.
|
||||
}
|
||||
|
||||
this._mm = null;
|
||||
},
|
||||
|
||||
// Because we implement nsIDOMGlobalPropertyInitializer, our init() method
|
||||
// is invoked with content window as its single argument.
|
||||
init: function nsDOMIdentityInternal_init(aWindow) {
|
||||
if (Services.prefs.getPrefType(PREF_ENABLED) != Ci.nsIPrefBranch.PREF_BOOL
|
||||
|| !Services.prefs.getBoolPref(PREF_ENABLED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this._debug =
|
||||
Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
|
||||
&& Services.prefs.getBoolPref(PREF_DEBUG);
|
||||
|
||||
// Setup identifiers for current window.
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
// To avoid cross-process windowId collisions, use a uuid as an
|
||||
// almost certainly unique identifier.
|
||||
//
|
||||
// XXX Bug 869182 - use a combination of child process id and
|
||||
// innerwindow id to construct the unique id.
|
||||
this._id = uuidgen.generateUUID().toString();
|
||||
this._window = aWindow;
|
||||
|
||||
// nsDOMIdentity needs to know our _id, so this goes after
|
||||
// its creation.
|
||||
this._initializeState();
|
||||
|
||||
// Store window and origin URI.
|
||||
this._window = aWindow;
|
||||
this._origin = aWindow.document.nodePrincipal.origin;
|
||||
this._appStatus = aWindow.document.nodePrincipal.appStatus;
|
||||
this._appId = aWindow.document.nodePrincipal.appId;
|
||||
|
||||
this._log("init was called from " + aWindow.document.location);
|
||||
|
||||
this._mm = cpmm;
|
||||
|
||||
// Setup listeners for messages from parent process.
|
||||
this._messages = [
|
||||
"Identity:ResetState",
|
||||
"Identity:RP:Watch:OnLogin",
|
||||
"Identity:RP:Watch:OnLogout",
|
||||
"Identity:RP:Watch:OnReady",
|
||||
"Identity:RP:Watch:OnCancel",
|
||||
"Identity:RP:Watch:OnError",
|
||||
"Identity:IDP:CallBeginProvisioningCallback",
|
||||
"Identity:IDP:CallGenKeyPairCallback",
|
||||
"Identity:IDP:CallBeginAuthenticationCallback"
|
||||
];
|
||||
this._messages.forEach(function(msgName) {
|
||||
this._mm.addMessageListener(msgName, this);
|
||||
}, this);
|
||||
|
||||
// Setup observers so we can remove message listeners.
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
},
|
||||
|
||||
uninit: function DOMIdentity_uninit() {
|
||||
this._log("nsDOMIdentity uninit() " + this._id);
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:RP:Unwatch",
|
||||
{ id: this._id }
|
||||
);
|
||||
},
|
||||
|
||||
// Private.
|
||||
_log: function nsDOMIdentityInternal__log(msg) {
|
||||
if (!this._debug) {
|
||||
return;
|
||||
}
|
||||
dump("nsDOMIdentity (" + this._id + "): " + msg + "\n");
|
||||
},
|
||||
|
||||
// Component setup.
|
||||
classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIMessageListener,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsIDOMGlobalPropertyInitializer
|
||||
]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
|
||||
contractID: "@mozilla.org/dom/identity;1",
|
||||
interfaces: [],
|
||||
classDescription: "Identity DOM Implementation"
|
||||
})
|
||||
};
|
||||
|
||||
function assertCorrectCallbacks(aOptions) {
|
||||
// The relying party (RP) provides callbacks on watch().
|
||||
//
|
||||
// In the future, BrowserID will probably only require an onlogin()
|
||||
// callback, lifting the requirement that BrowserID handle logged-in
|
||||
// state management for RPs. See
|
||||
// https://github.com/mozilla/id-specs/blob/greenfield/browserid/api-rp.md
|
||||
//
|
||||
// However, Firefox Accounts requires callers to provide onlogout(),
|
||||
// onready(), and also supports an onerror() callback.
|
||||
|
||||
let requiredCallbacks = ["onlogin"];
|
||||
let optionalCallbacks = ["onlogout", "onready", "onerror"];
|
||||
|
||||
if (aOptions.wantIssuer == "firefox-accounts") {
|
||||
requiredCallbacks = ["onlogin", "onlogout", "onready"];
|
||||
optionalCallbacks = ["onerror"];
|
||||
}
|
||||
|
||||
for (let cbName of requiredCallbacks) {
|
||||
if (typeof(aOptions[cbName]) != "function") {
|
||||
throw new Error(cbName + " callback is required.");
|
||||
}
|
||||
}
|
||||
|
||||
for (let cbName of optionalCallbacks) {
|
||||
if (aOptions[cbName] && typeof(aOptions[cbName]) != "function") {
|
||||
throw new Error(cbName + " must be a function");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentity]);
|
@ -1,35 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
this.IDService = function IDService() {
|
||||
this.wrappedJSObject = this;
|
||||
};
|
||||
|
||||
this.IDService.prototype = {
|
||||
classID: Components.ID("{4e0a0e98-b1d3-4745-a1eb-f815199dd06b}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "app-startup":
|
||||
Services.obs.addObserver(this, "final-ui-startup", true);
|
||||
break;
|
||||
case "final-ui-startup":
|
||||
// Startup DOMIdentity.jsm
|
||||
Cu.import("resource://gre/modules/DOMIdentity.jsm");
|
||||
DOMIdentity._init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([IDService]);
|
@ -1,18 +0,0 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'b2g'
|
||||
|
||||
support-files=
|
||||
file_browserid_rp_ok.html
|
||||
file_browserid_rp_noOnlogin.html
|
||||
file_declareAudience.html
|
||||
file_fxa_rp_ok.html
|
||||
file_fxa_rp_noOnready.html
|
||||
file_fxa_rp_noOnlogin.html
|
||||
file_fxa_rp_noOnlogout.html
|
||||
file_syntheticEvents.html
|
||||
|
||||
[test_declareAudience.html]
|
||||
[test_rpHasValidCallbacks.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_syntheticEvents.html]
|
||||
|
@ -1,44 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a bad RP. It does not provide an onlogin callback.
|
||||
// nsDOMIdentity will throw an exception when we call watch().
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({ });
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,43 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a happy RP. It has the expected callbacks for BrowserID.
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
onlogin: function() {},
|
||||
});
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,73 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Certified and packaged apps should be able to declare assertion audience.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=947374
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 947374</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id='test'>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
function postResults(message) {
|
||||
doPostMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: "firefox-accounts",
|
||||
audience: event.data.audience,
|
||||
onready: function() {
|
||||
try {
|
||||
navigator.mozId.request();
|
||||
} catch(e) {
|
||||
postResults({
|
||||
success: false,
|
||||
error: e,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
}
|
||||
},
|
||||
onlogin: function(backedAssertion) {
|
||||
postResults({
|
||||
success: true,
|
||||
backedAssertion: backedAssertion,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
},
|
||||
onerror: function(error) {
|
||||
postResults({
|
||||
success: false,
|
||||
error: error,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
},
|
||||
|
||||
// onlogout will actually be called every time watch() is invoked,
|
||||
// because fxa will find no signed-in user and so trigger logout.
|
||||
// For this test, though, we don't care and just ignore logout.
|
||||
onlogout: function () {},
|
||||
});
|
||||
} catch (e) {
|
||||
postResults({
|
||||
success: false,
|
||||
error: e,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,46 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a bad Firefox Accounts RP. It has no onlogin callback.
|
||||
// nsDOMIdentity will throw an exception.
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: "firefox-accounts",
|
||||
onready: function() {},
|
||||
onlogout: function() {},
|
||||
});
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,46 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a bad Firefox Accounts RP. It has no onlogout callback.
|
||||
// nsDOMIdentity will throw an exception.
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: "firefox-accounts",
|
||||
onlogin: function() {},
|
||||
onready: function() {},
|
||||
});
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,46 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a bad Firefox Accounts RP. It has no onready callback.
|
||||
// nsDOMIdentity will throw an exception.
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: "firefox-accounts",
|
||||
onlogin: function() {},
|
||||
onlogout: function() {},
|
||||
});
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,46 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
RPs have the correct callbacks for BrowserID or Firefox Accounts
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 945363</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// This is a happy RP. It has the expected callbacks for Firefox Accounts.
|
||||
|
||||
function postMessage(message) {
|
||||
SpecialPowers.wrap(window).parent
|
||||
.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
let error = false;
|
||||
|
||||
window.addEventListener('load', function onLoad(event) {
|
||||
window.removeEventListener('load', onLoad);
|
||||
try {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: "firefox-accounts",
|
||||
onready: function() {},
|
||||
onlogin: function() {},
|
||||
onlogout: function() {},
|
||||
});
|
||||
} catch(ex) {
|
||||
error = true;
|
||||
}
|
||||
postMessage({error: error});
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,61 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Certified and privileged apps can call mozId outside an event handler
|
||||
Certified apps: https://bugzilla.mozilla.org/show_bug.cgi?id=971379
|
||||
Privileged apps: https://bugzilla.mozilla.org/show_bug.cgi?id=982460
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app for bug 971379</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id='test'>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
function postResults(message) {
|
||||
doPostMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
navigator.mozId.watch({
|
||||
wantIssuer: event.data.wantIssuer,
|
||||
onready: function() {
|
||||
try {
|
||||
navigator.mozId.request();
|
||||
} catch(e) {
|
||||
postResults({
|
||||
success: false,
|
||||
error: e,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
}
|
||||
},
|
||||
onlogin: function(backedAssertion) {
|
||||
postResults({
|
||||
success: true,
|
||||
backedAssertion: backedAssertion,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
},
|
||||
onerror: function(error) {
|
||||
postResults({
|
||||
success: false,
|
||||
error: error,
|
||||
appIndex: event.data.appIndex
|
||||
});
|
||||
},
|
||||
onlogout: function() {},
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,289 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=947374
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Certified apps can changed the default audience of an assertion -- Bug 947374</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=947374">Mozilla Bug 947374</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/identity/jwcrypto.jsm");
|
||||
Components.utils.import("resource://gre/modules/identity/FirefoxAccounts.jsm");
|
||||
|
||||
// quick check to make sure we can test apps:
|
||||
is("appStatus" in document.nodePrincipal, true,
|
||||
"appStatus should be present in nsIPrincipal, if not the rest of this test will fail");
|
||||
|
||||
// Mock the Firefox Accounts manager to generate a keypair and provide a fake
|
||||
// cert for the caller on each getAssertion request.
|
||||
function MockFXAManager() {}
|
||||
|
||||
MockFXAManager.prototype = {
|
||||
getAssertion: function(audience, options) {
|
||||
// Always reject a request for a silent assertion, simulating the
|
||||
// scenario in which there is no signed-in user to begin with.
|
||||
if (options.silent) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
jwcrypto.generateKeyPair("DS160", (err, kp) => {
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
jwcrypto.generateAssertion("fake-cert", kp, audience, (err, assertion) => {
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
return deferred.resolve(assertion);
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
let originalManager = FirefoxAccounts.fxAccountsManager;
|
||||
FirefoxAccounts.fxAccountsManager = new MockFXAManager();
|
||||
|
||||
// The manifests for these apps are all declared in
|
||||
// /testing/profiles/webapps_mochitest.json. They are injected into the profile
|
||||
// by /testing/mochitest/runtests.py with the appropriate appStatus. So we don't
|
||||
// have to manually install any apps.
|
||||
//
|
||||
// For each app, we will use the file_declareAudience.html content to populate an
|
||||
// iframe. The iframe will request() a firefox accounts assertion. It will then
|
||||
// postMessage the results of this experiment back down to us, and we will
|
||||
// compare it with the expected results.
|
||||
let apps = [
|
||||
{
|
||||
title: "an installed app, which should neither be able to use FxA, nor change audience",
|
||||
manifest: "https://example.com/manifest.webapp",
|
||||
appStatus: Components.interfaces.nsIPrincipal.APP_STATUS_INSTALLED,
|
||||
origin: "https://example.com",
|
||||
wantAudience: "https://i-cant-have-this.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
|
||||
expected: {
|
||||
success: false,
|
||||
underprivileged: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "an app's assertion audience should be its origin by default",
|
||||
manifest: "https://example.com/manifest_priv.webapp",
|
||||
appStatus: Components.interfaces.nsIPrincipal.APP_STATUS_PRIVILEGED,
|
||||
origin: "https://example.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
|
||||
expected: {
|
||||
success: true,
|
||||
underprivileged: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "a privileged app, which may not have an audience other than its origin",
|
||||
manifest: "https://example.com/manifest_priv.webapp",
|
||||
appStatus: Components.interfaces.nsIPrincipal.APP_STATUS_PRIVILEGED,
|
||||
origin: "https://example.com",
|
||||
wantAudience: "https://i-like-pie.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
|
||||
expected: {
|
||||
success: false,
|
||||
underprivileged: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "a privileged app, which may declare an audience the same as its origin",
|
||||
manifest: "https://example.com/manifest_priv.webapp",
|
||||
appStatus: Components.interfaces.nsIPrincipal.APP_STATUS_PRIVILEGED,
|
||||
origin: "https://example.com",
|
||||
wantAudience: "https://example.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
|
||||
expected: {
|
||||
success: true,
|
||||
underprivileged: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "a certified app, which may do whatever it damn well pleases",
|
||||
manifest: "https://example.com/manifest_cert.webapp",
|
||||
appStatus: Components.interfaces.nsIPrincipal.APP_STATUS_CERTIFIED,
|
||||
origin: "https://example.com",
|
||||
wantAudience: "https://whatever-i-want.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
|
||||
expected: {
|
||||
success: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let eventsReceived = 0;
|
||||
let testRunner = runTest();
|
||||
|
||||
// Successful tests will send exactly one message. But for error tests, we may
|
||||
// have more than one message from the onerror handler in the client. So we keep
|
||||
// track of received errors; once they reach the expected count, we are done.
|
||||
function receiveMessage(event) {
|
||||
let result = JSON.parse(event.data);
|
||||
let app = apps[result.appIndex];
|
||||
if (app.received) {
|
||||
return;
|
||||
}
|
||||
apps[result.appIndex].received = true;
|
||||
|
||||
let expected = app.expected;
|
||||
|
||||
let expectedErrors = 0;
|
||||
let receivedErrors = [];
|
||||
|
||||
if (expected.underprivileged) {
|
||||
expectedErrors += 1;
|
||||
}
|
||||
if (expected.nopermission) {
|
||||
expectedErrors += 1;
|
||||
}
|
||||
|
||||
is(result.success, expected.success,
|
||||
"Assertion request succeeds");
|
||||
|
||||
if (expected.success) {
|
||||
// Confirm that the assertion audience and origin are as expected
|
||||
let components = extractAssertionComponents(result.backedAssertion);
|
||||
is(components.payload.aud, app.wantAudience || app.origin,
|
||||
"Got desired assertion audience");
|
||||
} else {
|
||||
receivedErrors.push(result.error);
|
||||
}
|
||||
|
||||
|
||||
ok(receivedErrors.length === expectedErrors,
|
||||
"Received errors should be equal to expected errors");
|
||||
|
||||
if (!expected.success && expected.underprivileged) {
|
||||
ok(receivedErrors.indexOf("ERROR_INVALID_ASSERTION_AUDIENCE") > -1,
|
||||
"Expect an error getting an assertion");
|
||||
}
|
||||
|
||||
eventsReceived += 1;
|
||||
|
||||
if (eventsReceived === apps.length) {
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
|
||||
FirefoxAccounts.fxAccountsManager = originalManager;
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
testRunner.next();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false, true);
|
||||
|
||||
function runTest() {
|
||||
let index;
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
dump("\n\n** Testing " + app.title + "\n");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
|
||||
iframe.setAttribute("mozapp", app.manifest);
|
||||
iframe.setAttribute("mozbrowser", "true");
|
||||
iframe.src = app.uri;
|
||||
|
||||
document.getElementById("content").appendChild(iframe);
|
||||
|
||||
index = i;
|
||||
(function(_index) {
|
||||
iframe.addEventListener("load", function onLoad() {
|
||||
iframe.removeEventListener("load", onLoad);
|
||||
|
||||
SpecialPowers.addPermission(
|
||||
"firefox-accounts",
|
||||
SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
iframe.contentDocument
|
||||
);
|
||||
|
||||
let principal = iframe.contentDocument.nodePrincipal;
|
||||
is(principal.appStatus, app.appStatus,
|
||||
"Iframe's document.nodePrincipal has expected appStatus");
|
||||
|
||||
// Because the <iframe mozapp> can't parent its way back to us, we
|
||||
// provide this handle it can use to postMessage to us.
|
||||
Components.utils.exportFunction(window.postMessage.bind(window), iframe.contentWindow, {defineAs: 'doPostMessage'});
|
||||
|
||||
// Test what we want to test, viz. whether or not the app can request
|
||||
// an assertion with an audience the same as or different from its
|
||||
// origin. The client will post back its success or failure in procuring
|
||||
// an identity assertion from Firefox Accounts.
|
||||
iframe.contentWindow.postMessage({
|
||||
audience: app.wantAudience,
|
||||
appIndex: _index
|
||||
}, "*");
|
||||
}, false);
|
||||
})(index);
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function extractAssertionComponents(backedAssertion) {
|
||||
let [_, signedObject] = backedAssertion.split("~");
|
||||
let parts = signedObject.split(".");
|
||||
|
||||
let headerSegment = parts[0];
|
||||
let payloadSegment = parts[1];
|
||||
let cryptoSegment = parts[2];
|
||||
|
||||
let header = JSON.parse(base64UrlDecode(headerSegment));
|
||||
let payload = JSON.parse(base64UrlDecode(payloadSegment));
|
||||
|
||||
return {header: header,
|
||||
payload: payload,
|
||||
headerSegment: headerSegment,
|
||||
payloadSegment: payloadSegment,
|
||||
cryptoSegment: cryptoSegment};
|
||||
};
|
||||
|
||||
function base64UrlDecode(s) {
|
||||
s = s.replace(/-/g, "+");
|
||||
s = s.replace(/_/g, "/");
|
||||
// Don't need to worry about reintroducing padding ('=='), since
|
||||
// jwcrypto provides that.
|
||||
return atob(s);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set":
|
||||
[
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.identity.enabled", true],
|
||||
["identity.fxaccounts.enabled", true],
|
||||
["toolkit.identity.debug", true],
|
||||
["dom.identity.syntheticEventsOk", true],
|
||||
["security.apps.privileged.CSP.default", "'inline-script';"],
|
||||
["security.apps.certified.CSP.default", "'inline-script';"],
|
||||
]},
|
||||
function() {
|
||||
testRunner.next();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,97 +0,0 @@
|
||||
<!--
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=945363
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BrowserID and Firefox Accounts RPs provide requried callbacks - Bug 945363</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=945363">Mozilla Bug 945363</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 945363 **/
|
||||
|
||||
const BASE_URL = "http://mochi.test:8888/chrome/dom/identity/tests/mochitest/";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Candidate RPs, and whether we expect them to experience an error.
|
||||
// Will will load each of these in turn into an iframe. The candiates
|
||||
// will invoke navigator.mozId.watch(). If they do not provide the
|
||||
// correct arguments to watch(), nsDOMIdentity will throw an exception.
|
||||
let candidates = [
|
||||
[BASE_URL + "file_browserid_rp_ok.html", false],
|
||||
[BASE_URL + "file_browserid_rp_noOnlogin.html", true ],
|
||||
[BASE_URL + "file_fxa_rp_ok.html", false],
|
||||
[BASE_URL + "file_fxa_rp_noOnlogin.html", true ],
|
||||
[BASE_URL + "file_fxa_rp_noOnlogout.html", true ],
|
||||
[BASE_URL + "file_fxa_rp_noOnready.html", true ],
|
||||
];
|
||||
|
||||
let checkedCount = 0;
|
||||
let checksTodo = candidates.length;
|
||||
|
||||
// Each iframe will postMessage to us, telling us whether they caught
|
||||
// an exception or not when calling watch().
|
||||
window.addEventListener('message', function onMessage(event) {
|
||||
let message = JSON.parse(event.data);
|
||||
let [uri, expectedError] = candidates[checkedCount];
|
||||
|
||||
is(message.error, expectedError, "Unexpected error result from " + uri);
|
||||
|
||||
if (++checkedCount < checksTodo) {
|
||||
testRunner.next();
|
||||
} else {
|
||||
window.removeEventListener('message', onMessage);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}, false);
|
||||
|
||||
let content = document.getElementById('content');
|
||||
function runTest() {
|
||||
for (let [uri, _] of candidates) {
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.src = uri;
|
||||
|
||||
content.appendChild(iframe);
|
||||
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
let testRunner = runTest();
|
||||
|
||||
// Enable the identity systems and use verbose logging
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.identity.enabled', true], // navigator.mozId
|
||||
['identity.fxaccounts.enabled', true], // fx accounts
|
||||
['dom.identity.syntheticEventsOk', true], // so we can call request()
|
||||
['toolkit.identity.debug', true], // verbose identity logging
|
||||
['browser.dom.window.dump.enabled', true],
|
||||
["security.apps.privileged.CSP.default", "'inline-script';"],
|
||||
["security.apps.certified.CSP.default", "'inline-script';"],
|
||||
]},
|
||||
function () { testRunner.next(); }
|
||||
);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,210 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=971379
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Certified/packaged apps may use synthetic events with FXA -- Bug 971379</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=971379">Mozilla Bug 971379</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/DOMIdentity.jsm");
|
||||
Components.utils.import("resource://gre/modules/identity/jwcrypto.jsm");
|
||||
Components.utils.import("resource://gre/modules/identity/FirefoxAccounts.jsm");
|
||||
|
||||
// Mock the Firefox Accounts manager to give a dummy assertion, just to confirm
|
||||
// that we're making the trip through the dom/identity and toolkit/identity
|
||||
// plumbing.
|
||||
function MockFXAManager() {}
|
||||
MockFXAManager.prototype = {
|
||||
getAssertion: function(audience, options) {
|
||||
if (options.silent) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return Promise.resolve("here~you.go.dude");
|
||||
}
|
||||
};
|
||||
|
||||
let originalManager = FirefoxAccounts.fxAccountsManager;
|
||||
FirefoxAccounts.fxAccountsManager = new MockFXAManager();
|
||||
|
||||
// Mock IdentityService (Persona) so we can test request() while not handling
|
||||
// user input on an installed app. Since in this test suite, we have only this
|
||||
// one test for Persona, we additionally cause request() to throw if invoked, as
|
||||
// added security that nsDOMIdentity did not emit a request message.
|
||||
let MockIdentityService = function() {
|
||||
this.RP = this;
|
||||
this.contexts = {};
|
||||
}
|
||||
MockIdentityService.prototype = {
|
||||
watch: function(context) {
|
||||
this.contexts[context.id] = context;
|
||||
context.doReady();
|
||||
},
|
||||
|
||||
request: function(message) {
|
||||
ok(false, "nsDOMIdentity should block Persona request() in this test suite");
|
||||
},
|
||||
};
|
||||
DOMIdentity._mockIdentityService = new MockIdentityService();
|
||||
|
||||
// The manifests for these apps are all declared in
|
||||
// /testing/profiles/webapps_mochitest.json. They are injected into the profile
|
||||
// by /testing/mochitest/runtests.py with the appropriate appStatus. So we don't
|
||||
// have to manually install any apps.
|
||||
let apps = [
|
||||
{
|
||||
title: "an installed app, which must request() in a native event",
|
||||
manifest: "https://example.com/manifest.webapp",
|
||||
origin: "https://example.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html",
|
||||
wantIssuer: "", // default to persona
|
||||
expected: {
|
||||
success: false,
|
||||
errors: [
|
||||
"ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "a privileged app, which may use synthetic events",
|
||||
manifest: "https://example.com/manifest_priv.webapp",
|
||||
origin: "https://example.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html",
|
||||
wantIssuer: "firefox-accounts",
|
||||
expected: {
|
||||
success: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "a certified app, which may use synthetic events",
|
||||
manifest: "https://example.com/manifest_cert.webapp",
|
||||
origin: "https://example.com",
|
||||
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html",
|
||||
wantIssuer: "firefox-accounts",
|
||||
expected: {
|
||||
success: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let eventsReceived = 0;
|
||||
let testRunner = runTest();
|
||||
|
||||
function receiveMessage(event) {
|
||||
dump("** Received response: " + event.data + "\n");
|
||||
let result = JSON.parse(event.data);
|
||||
let app = apps[result.appIndex];
|
||||
if (app.received) {
|
||||
return;
|
||||
}
|
||||
apps[result.appIndex].received = true;
|
||||
|
||||
let expected = app.expected;
|
||||
let receivedErrors = [];
|
||||
|
||||
is(result.success, expected.success,
|
||||
"Assertion request " + (expected.success ? "succeeds" : "fails"));
|
||||
|
||||
if (result.error) {
|
||||
receivedErrors.push(result.error);
|
||||
}
|
||||
|
||||
ok(receivedErrors.length === (expected.errors || []).length,
|
||||
"Received errors should be equal to expected errors");
|
||||
|
||||
receivedErrors.forEach((error) => {
|
||||
ok(expected.errors.indexOf(error) > -1,
|
||||
"Received " + error + ". " +
|
||||
"Expected errors are: " + JSON.stringify(expected.errors));
|
||||
});
|
||||
|
||||
eventsReceived += 1;
|
||||
|
||||
if (eventsReceived === apps.length) {
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
|
||||
FirefoxAccounts.fxAccountsManager = originalManager;
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
testRunner.next();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false, true);
|
||||
|
||||
function runTest() {
|
||||
let index;
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
dump("** Testing " + app.title + "\n");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
|
||||
iframe.setAttribute("mozapp", app.manifest);
|
||||
iframe.setAttribute("mozbrowser", "true");
|
||||
iframe.src = app.uri;
|
||||
|
||||
document.getElementById("content").appendChild(iframe);
|
||||
|
||||
index = i;
|
||||
(function(_index) {
|
||||
iframe.addEventListener("load", function onLoad() {
|
||||
iframe.removeEventListener("load", onLoad);
|
||||
|
||||
SpecialPowers.addPermission(
|
||||
"firefox-accounts",
|
||||
SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
iframe.contentDocument
|
||||
);
|
||||
|
||||
// Because the <iframe mozapp> can't parent its way back to us, we
|
||||
// provide this handle it can use to postMessage to us.
|
||||
Components.utils.exportFunction(window.postMessage.bind(window), iframe.contentWindow, {defineAs: 'doPostMessage'});
|
||||
|
||||
iframe.contentWindow.postMessage({
|
||||
wantIssuer: app.wantIssuer,
|
||||
appIndex: _index
|
||||
}, "*");
|
||||
}, false);
|
||||
})(index);
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set":
|
||||
[
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.identity.enabled", true],
|
||||
["identity.fxaccounts.enabled", true],
|
||||
["toolkit.identity.debug", true],
|
||||
["security.apps.privileged.CSP.default", "'inline-script';"],
|
||||
["security.apps.certified.CSP.default", "'inline-script';"],
|
||||
]},
|
||||
function() {
|
||||
testRunner.next();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -139,7 +139,6 @@ if CONFIG['MOZ_SECUREELEMENT']:
|
||||
if CONFIG['MOZ_B2G']:
|
||||
DIRS += [
|
||||
'downloads',
|
||||
'identity'
|
||||
]
|
||||
|
||||
DIRS += ['presentation']
|
||||
|
@ -1,70 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
callback IdentityOnReadyCallback = void();
|
||||
callback IdentityOnLoginCallback = void(DOMString identityAssertion);
|
||||
callback IdentityOnLogoutCallback = void();
|
||||
callback IdentityOnCancelCallback = void(DOMString? error);
|
||||
callback IdentityOnErrorCallback = void(DOMString error);
|
||||
|
||||
dictionary IdentityWatchOptions {
|
||||
// Required callback
|
||||
IdentityOnLoginCallback onlogin;
|
||||
|
||||
// Optional parameters
|
||||
DOMString wantIssuer;
|
||||
DOMString loggedInUser;
|
||||
|
||||
// Optional callbacks
|
||||
IdentityOnReadyCallback onready;
|
||||
IdentityOnLogoutCallback onlogout;
|
||||
IdentityOnErrorCallback onerror;
|
||||
|
||||
// Certified apps can specify this
|
||||
DOMString audience;
|
||||
};
|
||||
|
||||
dictionary IdentityRequestOptions {
|
||||
// Optional parameters
|
||||
long refreshAuthentication;
|
||||
DOMString termsOfService;
|
||||
DOMString privacyPolicy;
|
||||
DOMString backgroundColor;
|
||||
DOMString siteLogo;
|
||||
DOMString siteName;
|
||||
DOMString returnTo;
|
||||
|
||||
IdentityOnCancelCallback oncancel;
|
||||
|
||||
// Certified apps can specify this
|
||||
DOMString origin;
|
||||
};
|
||||
|
||||
dictionary IdentityGetOptions {
|
||||
DOMString privacyPolicy;
|
||||
DOMString termsOfService;
|
||||
DOMString privacyURL;
|
||||
DOMString tosURL;
|
||||
DOMString siteName;
|
||||
DOMString siteLogo;
|
||||
};
|
||||
|
||||
[JSImplementation="@mozilla.org/identity/manager;1",
|
||||
NoInterfaceObject,
|
||||
NavigatorProperty="mozId",
|
||||
Pref="dom.identity.enabled"]
|
||||
interface IdentityManager {
|
||||
void watch(optional IdentityWatchOptions options);
|
||||
void request(optional IdentityRequestOptions options);
|
||||
void logout();
|
||||
|
||||
[Pref="dom.identity.exposeLegacyGetAPI"]
|
||||
void get(IdentityOnLoginCallback callback, optional IdentityGetOptions options);
|
||||
|
||||
[Pref="dom.identity.exposeLegacyGetVerifiedEmailAPI"]
|
||||
void getVerifiedEmail(IdentityOnLoginCallback callback);
|
||||
};
|
||||
|
@ -905,7 +905,6 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
|
||||
if CONFIG['MOZ_B2G']:
|
||||
WEBIDL_FILES += [
|
||||
'Apps.webidl',
|
||||
'Identity.webidl',
|
||||
'MozApplicationEvent.webidl'
|
||||
]
|
||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||
|
@ -116,7 +116,6 @@ function runTest() {
|
||||
};
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.identity.enabled", true], // navigator.mozId
|
||||
["identity.fxaccounts.enabled", true], // fx accounts
|
||||
["identity.fxaccounts.auth.uri", TEST_SERVER], // our sjs server
|
||||
["toolkit.identity.debug", true], // verbose identity logging
|
||||
|
Loading…
Reference in New Issue
Block a user