зеркало из https://github.com/mozilla/gecko-dev.git
Backout 7d1b925bd4ee and 52e5b438c911 (Bug 753239) due to almost permaorange.
This commit is contained in:
Родитель
13fc9bf9b8
Коммит
fee43a9dcb
|
@ -474,9 +474,6 @@
|
|||
@BINPATH@/components/Webapps.manifest
|
||||
@BINPATH@/components/AppsService.js
|
||||
@BINPATH@/components/AppsService.manifest
|
||||
@BINPATH@/components/nsDOMIdentity.js
|
||||
@BINPATH@/components/nsIDService.js
|
||||
@BINPATH@/components/Identity.manifest
|
||||
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
|
|
|
@ -67,7 +67,6 @@ DIRS += \
|
|||
indexedDB \
|
||||
system \
|
||||
ipc \
|
||||
identity \
|
||||
workers \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1,266 +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;
|
||||
|
||||
// This is the parent process corresponding to nsDOMIdentity.
|
||||
let EXPORTED_SYMBOLS = ["DOMIdentity"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
|
||||
"resource://gre/modules/identity/Identity.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
"Logger",
|
||||
"resource://gre/modules/identity/LogUtils.jsm");
|
||||
|
||||
function log(...aMessageArgs) {
|
||||
Logger.log(["DOMIdentity"].concat(aMessageArgs));
|
||||
}
|
||||
|
||||
function IDDOMMessage(aID) {
|
||||
this.id = aID;
|
||||
}
|
||||
|
||||
function IDPProvisioningContext(aID, aOrigin, aTargetMM) {
|
||||
this._id = aID;
|
||||
this._origin = aOrigin;
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
IDPProvisioningContext.prototype = {
|
||||
get id() this._id,
|
||||
get origin() this._origin,
|
||||
|
||||
doBeginProvisioningCallback: function IDPPC_doBeginProvCB(aID, aCertDuration) {
|
||||
let message = new IDDOMMessage(this.id);
|
||||
message.identity = aID;
|
||||
message.certDuration = aCertDuration;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CallBeginProvisioningCallback",
|
||||
message);
|
||||
},
|
||||
|
||||
doGenKeyPairCallback: function IDPPC_doGenKeyPairCallback(aPublicKey) {
|
||||
log("doGenKeyPairCallback");
|
||||
let message = new IDDOMMessage(this.id);
|
||||
message.publicKey = aPublicKey;
|
||||
this._mm.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() this._id,
|
||||
get origin() this._origin,
|
||||
|
||||
doBeginAuthenticationCallback: function IDPAC_doBeginAuthCB(aIdentity) {
|
||||
let message = new IDDOMMessage(this.id);
|
||||
message.identity = aIdentity;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CallBeginAuthenticationCallback",
|
||||
message);
|
||||
},
|
||||
|
||||
doError: function IDPAC_doError(msg) {
|
||||
log("Authentication ERROR: " + msg);
|
||||
},
|
||||
};
|
||||
|
||||
function RPWatchContext(aID, aOrigin, aLoggedInEmail, aTargetMM) {
|
||||
this._id = aID;
|
||||
this._origin = aOrigin;
|
||||
this._loggedInEmail = aLoggedInEmail;
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
RPWatchContext.prototype = {
|
||||
get id() this._id,
|
||||
get origin() this._origin,
|
||||
get loggedInEmail() this._loggedInEmail,
|
||||
|
||||
doLogin: function RPWatchContext_onlogin(aAssertion) {
|
||||
log("doLogin: " + this.id);
|
||||
let message = new IDDOMMessage(this.id);
|
||||
message.assertion = aAssertion;
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch:OnLogin", message);
|
||||
},
|
||||
|
||||
doLogout: function RPWatchContext_onlogout() {
|
||||
log("doLogout :" + this.id);
|
||||
let message = new IDDOMMessage(this.id);
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch:OnLogout", message);
|
||||
},
|
||||
|
||||
doReady: function RPWatchContext_onready() {
|
||||
log("doReady: " + this.id);
|
||||
let message = new IDDOMMessage(this.id);
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch:OnReady", message);
|
||||
},
|
||||
|
||||
doError: function RPWatchContext_onerror(aMessage) {
|
||||
log("doError: " + aMessage);
|
||||
}
|
||||
};
|
||||
|
||||
let DOMIdentity = {
|
||||
// nsIFrameMessageListener
|
||||
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
|
||||
.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
|
||||
switch (aMessage.name) {
|
||||
// RP
|
||||
case "Identity:RP:Watch":
|
||||
this._watch(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;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function DOMIdentity_observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "domwindowopened":
|
||||
case "domwindowclosed":
|
||||
let win = aSubject.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
this._configureMessages(win, aTopic == "domwindowopened");
|
||||
break;
|
||||
|
||||
case "xpcom-shutdown":
|
||||
Services.ww.unregisterNotification(this);
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
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"],
|
||||
|
||||
// Private.
|
||||
_init: function DOMIdentity__init() {
|
||||
Services.ww.registerNotification(this);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
_configureMessages: function DOMIdentity__configureMessages(aWindow, aRegister) {
|
||||
if (!aWindow.messageManager)
|
||||
return;
|
||||
|
||||
let func = aWindow.messageManager[aRegister ? "addMessageListener"
|
||||
: "removeMessageListener"];
|
||||
|
||||
for (let message of this.messages) {
|
||||
func(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
_resetFrameState: function(aContext) {
|
||||
log("_resetFrameState: ", aContext.id);
|
||||
if (!aContext._mm) {
|
||||
throw new Error("ERROR: Trying to reset an invalid context");
|
||||
}
|
||||
let message = new IDDOMMessage(aContext.id);
|
||||
aContext._mm.sendAsyncMessage("Identity:ResetState", message);
|
||||
},
|
||||
|
||||
_watch: function DOMIdentity__watch(message, targetMM) {
|
||||
log("DOMIdentity__watch: " + message.id);
|
||||
// Pass an object with the watch members to Identity.jsm so it can call the
|
||||
// callbacks.
|
||||
let context = new RPWatchContext(message.id, message.origin,
|
||||
message.loggedInEmail, targetMM);
|
||||
IdentityService.RP.watch(context);
|
||||
},
|
||||
|
||||
_request: function DOMIdentity__request(message) {
|
||||
IdentityService.RP.request(message.id, message);
|
||||
},
|
||||
|
||||
_logout: function DOMIdentity__logout(message) {
|
||||
IdentityService.RP.logout(message.id, message.origin);
|
||||
},
|
||||
|
||||
_beginProvisioning: function DOMIdentity__beginProvisioning(message, targetMM) {
|
||||
let context = new IDPProvisioningContext(message.id, message.origin,
|
||||
targetMM);
|
||||
IdentityService.IDP.beginProvisioning(context);
|
||||
},
|
||||
|
||||
_genKeyPair: function DOMIdentity__genKeyPair(message) {
|
||||
IdentityService.IDP.genKeyPair(message.id);
|
||||
},
|
||||
|
||||
_registerCertificate: function DOMIdentity__registerCertificate(message) {
|
||||
IdentityService.IDP.registerCertificate(message.id, message.cert);
|
||||
},
|
||||
|
||||
_provisioningFailure: function DOMIdentity__provisioningFailure(message) {
|
||||
IdentityService.IDP.raiseProvisioningFailure(message.id, message.reason);
|
||||
},
|
||||
|
||||
_beginAuthentication: function DOMIdentity__beginAuthentication(message, targetMM) {
|
||||
let context = new IDPAuthenticationContext(message.id, message.origin,
|
||||
targetMM);
|
||||
IdentityService.IDP.beginAuthentication(context);
|
||||
},
|
||||
|
||||
_completeAuthentication: function DOMIdentity__completeAuthentication(message) {
|
||||
IdentityService.IDP.completeAuthentication(message.id);
|
||||
},
|
||||
|
||||
_authenticationFailure: function DOMIdentity__authenticationFailure(message) {
|
||||
IdentityService.IDP.cancelAuthentication(message.id);
|
||||
},
|
||||
};
|
||||
|
||||
// Object is initialized by nsIDService.js
|
|
@ -1,9 +0,0 @@
|
|||
# nsDOMIdentity.js
|
||||
component {8bcac6a3-56a4-43a4-a44c-cdf42763002f} nsDOMIdentity.js
|
||||
contract @mozilla.org/dom/identity;1 {8bcac6a3-56a4-43a4-a44c-cdf42763002f}
|
||||
category JavaScript-navigator-property id @mozilla.org/dom/identity;1
|
||||
|
||||
# nsIDService.js (initialization on startup)
|
||||
component {baa581e5-8e72-406c-8c9f-dcd4b23a6f82} nsIDService.js
|
||||
contract @mozilla.org/dom/identity/service;1 {baa581e5-8e72-406c-8c9f-dcd4b23a6f82}
|
||||
category app-startup IDService @mozilla.org/dom/identity/service;1
|
|
@ -1,28 +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/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/identity
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
nsDOMIdentity.js \
|
||||
nsIDService.js \
|
||||
Identity.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
DOMIdentity.jsm \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -1,530 +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";
|
||||
|
||||
// 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");
|
||||
|
||||
// This is the child process corresponding to nsIDOMIdentity.
|
||||
|
||||
|
||||
function nsDOMIdentity(aIdentityInternal) {
|
||||
this._identityInternal = aIdentityInternal;
|
||||
}
|
||||
nsDOMIdentity.prototype = {
|
||||
__exposedProps__: {
|
||||
// Relying Party (RP)
|
||||
watch: 'r',
|
||||
request: 'r',
|
||||
logout: 'r',
|
||||
|
||||
// Provisioning
|
||||
beginProvisioning: 'r',
|
||||
genKeyPair: 'r',
|
||||
registerCertificate: 'r',
|
||||
raiseProvisioningFailure: 'r',
|
||||
|
||||
// Authentication
|
||||
beginAuthentication: 'r',
|
||||
completeAuthentication: 'r',
|
||||
raiseAuthenticationFailure: 'r',
|
||||
},
|
||||
|
||||
// nsIDOMIdentity
|
||||
/**
|
||||
* Relying Party (RP) APIs
|
||||
*/
|
||||
|
||||
watch: function nsDOMIdentity_watch(aOptions) {
|
||||
this._log("watch");
|
||||
if (this._rpWatcher) {
|
||||
throw new Error("navigator.id.watch was already called");
|
||||
}
|
||||
|
||||
if (!aOptions || typeof(aOptions) !== "object") {
|
||||
throw new Error("options argument to watch is required");
|
||||
}
|
||||
|
||||
// Check for required callbacks
|
||||
let requiredCallbacks = ["onlogin", "onlogout"];
|
||||
for (let cbName of requiredCallbacks) {
|
||||
if ((!(cbName in aOptions))
|
||||
|| typeof(aOptions[cbName]) !== "function") {
|
||||
throw new Error(cbName + " callback is required.");
|
||||
}
|
||||
}
|
||||
|
||||
// Optional callback "onready"
|
||||
if (aOptions["onready"]
|
||||
&& typeof(aOptions['onready']) !== "function") {
|
||||
throw new Error("onready must be a function");
|
||||
}
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
|
||||
// loggedInEmail
|
||||
message.loggedInEmail = null;
|
||||
let emailType = typeof(aOptions["loggedInEmail"]);
|
||||
if (aOptions["loggedInEmail"] && aOptions["loggedInEmail"] !== "undefined") {
|
||||
if (emailType !== "string") {
|
||||
throw new Error("loggedInEmail must be a String or null");
|
||||
}
|
||||
|
||||
// TODO: Bug 767610 - check email format.
|
||||
// See nsHTMLInputElement::IsValidEmailAddress
|
||||
if (aOptions["loggedInEmail"].indexOf("@") == -1
|
||||
|| aOptions["loggedInEmail"].length > MAX_STRING_LENGTH) {
|
||||
throw new Error("loggedInEmail is not valid");
|
||||
}
|
||||
// Set loggedInEmail in this block that "undefined" doesn't get through.
|
||||
message.loggedInEmail = aOptions.loggedInEmail;
|
||||
}
|
||||
this._log("loggedInEmail: " + message.loggedInEmail);
|
||||
|
||||
this._rpWatcher = aOptions;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
|
||||
},
|
||||
|
||||
request: function nsDOMIdentity_request(aOptions) {
|
||||
// TODO: Bug 769569 - "must be invoked from within a click handler"
|
||||
|
||||
// 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 message = this.DOMIdentityMessage();
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:RP:Request", message);
|
||||
},
|
||||
|
||||
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();
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Logout", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
|
||||
},
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
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._identityInternal._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
|
||||
},
|
||||
|
||||
// Private.
|
||||
_init: function nsDOMIdentity__init(aWindow) {
|
||||
|
||||
this._initializeState();
|
||||
|
||||
// Store window and origin URI.
|
||||
this._window = aWindow;
|
||||
this._origin = aWindow.document.nodePrincipal.origin;
|
||||
|
||||
// Setup identifiers for current window.
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
this._id = util.outerWindowID;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
_receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
this._log("receiveMessage: " + aMessage.name);
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Identity:ResetState":
|
||||
if (!this._identityInternal._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) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onlogin) {
|
||||
this._rpWatcher.onlogin(msg.assertion);
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnLogout":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onlogout) {
|
||||
this._rpWatcher.onlogout();
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Watch:OnReady":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._rpWatcher.onready) {
|
||||
this._rpWatcher.onready();
|
||||
}
|
||||
break;
|
||||
case "Identity:RP:Request:OnCancel":
|
||||
// Do we have a watcher?
|
||||
if (!this._rpWatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._onCancelRequestCallback) {
|
||||
this._onCancelRequestCallback();
|
||||
}
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
_log: function nsDOMIdentity__log(msg) {
|
||||
this._identityInternal._log(msg);
|
||||
},
|
||||
|
||||
_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
|
||||
*/
|
||||
DOMIdentityMessage: function DOMIdentityMessage() {
|
||||
return {
|
||||
id: this._id,
|
||||
origin: this._origin,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal functions that shouldn't be exposed to content.
|
||||
*/
|
||||
function nsDOMIdentityInternal() {
|
||||
}
|
||||
nsDOMIdentityInternal.prototype = {
|
||||
|
||||
// nsIFrameMessageListener
|
||||
receiveMessage: function nsDOMIdentityInternal_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
// Is this message intended for this window?
|
||||
if (msg.id != this._id) {
|
||||
return;
|
||||
}
|
||||
this._identity._receiveMessage(aMessage);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function nsDOMIdentityInternal_observe(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId != this._innerWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._identity._initializeState();
|
||||
this._identity = null;
|
||||
|
||||
// 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;
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer
|
||||
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);
|
||||
|
||||
this._identity = new nsDOMIdentity(this);
|
||||
|
||||
this._identity._init(aWindow);
|
||||
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
this._id = util.outerWindowID;
|
||||
this._innerWindowID = util.currentInnerWindowID;
|
||||
|
||||
this._log("init was called from " + aWindow.document.location);
|
||||
|
||||
this._mm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
|
||||
// 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:Request:OnCancel",
|
||||
"Identity:IDP:CallBeginProvisioningCallback",
|
||||
"Identity:IDP:CallGenKeyPairCallback",
|
||||
"Identity:IDP:CallBeginAuthenticationCallback",
|
||||
];
|
||||
this._messages.forEach((function(msgName) {
|
||||
this._mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
// Setup observers so we can remove message listeners.
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
|
||||
return this._identity;
|
||||
},
|
||||
|
||||
// Private.
|
||||
_log: function nsDOMIdentityInternal__log(msg) {
|
||||
if (!this._debug) {
|
||||
return;
|
||||
}
|
||||
dump("nsDOMIdentity (" + this._id + "): " + msg + "\n");
|
||||
},
|
||||
|
||||
// Component setup.
|
||||
classID: Components.ID("{8bcac6a3-56a4-43a4-a44c-cdf42763002f}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI(
|
||||
[Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIFrameMessageListener]
|
||||
),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: Components.ID("{8bcac6a3-56a4-43a4-a44c-cdf42763002f}"),
|
||||
contractID: "@mozilla.org/dom/identity;1",
|
||||
interfaces: [],
|
||||
classDescription: "Identity DOM Implementation"
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentityInternal]);
|
|
@ -1,34 +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");
|
||||
|
||||
function IDService() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
IDService.prototype = {
|
||||
classID: Components.ID("{baa581e5-8e72-406c-8c9f-dcd4b23a6f82}"),
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([IDService]);
|
|
@ -1,28 +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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/identity/tests
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
head_identity.js \
|
||||
test_identity_idp_auth_basics.html \
|
||||
test_identity_idp_prov_basics.html \
|
||||
test_identity_rp_basics.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = SpecialPowers.wrap(Components).utils;
|
||||
|
||||
SpecialPowers.setBoolPref("toolkit.identity.debug", true);
|
||||
SpecialPowers.setBoolPref("dom.identity.enabled", true);
|
||||
|
||||
const Services = Cu.import("resource://gre/modules/Services.jsm").Services;
|
||||
const DOMIdentity = Cu.import("resource://gre/modules/DOMIdentity.jsm")
|
||||
.DOMIdentity;
|
||||
|
||||
let util = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let outerWinId = util.outerWindowID;
|
||||
|
||||
const identity = navigator.id || navigator.mozId;
|
||||
|
||||
let index = 0;
|
||||
|
||||
// mimicking callback funtionality for ease of testing
|
||||
// this observer auto-removes itself after the observe function
|
||||
// is called, so this is meant to observe only ONE event.
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
function observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == aObserveTopic) {
|
||||
aObserveFunc(aSubject, aTopic, aData);
|
||||
Services.obs.removeObserver(this, aObserveTopic);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observe, aObserveTopic, false);
|
||||
}
|
||||
|
||||
function expectException(aFunc, msg, aErrorType="Error") {
|
||||
info("Expecting an exception: " + msg);
|
||||
msg = msg || "";
|
||||
let caughtEx = null;
|
||||
try {
|
||||
aFunc();
|
||||
} catch (ex) {
|
||||
let exProto = Object.getPrototypeOf(ex);
|
||||
// Don't count NS_* exceptions since they shouldn't be exposed to content
|
||||
if (exProto.toString() == aErrorType
|
||||
&& ex.toString().indexOf("NS_ERROR_FAILURE") == -1) {
|
||||
caughtEx = ex;
|
||||
} else {
|
||||
ok(false, ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
isnot(caughtEx, null, "Check for thrown exception.");
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (!identity) {
|
||||
todo(false, "DOM API is not available. Skipping tests.");
|
||||
finish_tests();
|
||||
return;
|
||||
}
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let fn = steps[index];
|
||||
info("Begin test " + index + " '" + steps[index].name + "'!");
|
||||
fn();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
function finish_tests() {
|
||||
info("all done");
|
||||
SpecialPowers.clearUserPref("toolkit.identity.debug");
|
||||
SpecialPowers.clearUserPref("dom.identity.enabled");
|
||||
SimpleTest.finish();
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for navigator.id identity provider (IDP) authentication basics</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank">navigator.id identity provider (IDP) authentication basics</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
"use strict"
|
||||
|
||||
let steps = [
|
||||
// completeAuthentication tests
|
||||
function completeAuthenticationExists() {
|
||||
is(typeof(identity.completeAuthentication), "function",
|
||||
"Check completeAuthentication is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function completeAuthenticationOutsideFlow() {
|
||||
expectException(function() {
|
||||
identity.completeAuthentication();
|
||||
}, "Check completeAuthentication outside of an auth. flow");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// raiseAuthenticationFailure tests
|
||||
function raiseAuthenticationFailureExists() {
|
||||
is(typeof(identity.raiseAuthenticationFailure), "function",
|
||||
"Check raiseAuthenticationFailure is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function raiseAuthenticationFailureNoArgs() {
|
||||
expectException(function() {
|
||||
identity.raiseAuthenticationFailure();
|
||||
}, "raiseAuthenticationFailure with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// beginAuthentication tests
|
||||
function beginAuthenticationExists() {
|
||||
is(typeof(identity.beginAuthentication), "function",
|
||||
"Check beginAuthentication is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginAuthenticationNoArgs() {
|
||||
expectException(function() {
|
||||
identity.beginAuthentication();
|
||||
}, "beginAuthentication with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginAuthenticationInvalidArg() {
|
||||
expectException(function() {
|
||||
identity.beginAuthentication(999);
|
||||
}, "beginAuthentication with a non-function argument");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginAuthenticationArgs() {
|
||||
function beginAuthenticationCb() {
|
||||
throw "beginAuthentication callback shouldn't have been called outside of an "
|
||||
+ "auth flow";
|
||||
}
|
||||
is(identity.beginAuthentication(beginAuthenticationCb), undefined,
|
||||
"Check minimum beginAuthentication arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
finish_tests,
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(next);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,160 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for navigator.id identity provider (IDP) provisioning basics</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank">navigator.id identity provider (IDP) provisioning basics</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
"use strict"
|
||||
|
||||
let IDP = Cu.import("resource://gre/modules/identity/IdentityProvider.jsm").IdentityProvider;
|
||||
|
||||
function setupProv() {
|
||||
info("setupProv");
|
||||
// Add a provisioning flow so the DOM calls succeed
|
||||
IDP._provisionFlows[outerWinId] = {
|
||||
sandbox: {},
|
||||
callback: function doCallback(aErr) {
|
||||
info("provisioning callback: " + aErr);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function resetAndNext() {
|
||||
info("resetAndNext");
|
||||
// reset DOM state for the next test
|
||||
// Give the flow some time to cross the IPC boundary
|
||||
setTimeout(function() {
|
||||
let provContext = IDP._provisionFlows[outerWinId];
|
||||
if (!provContext) {
|
||||
SimpleTest.executeSoon(next);
|
||||
return;
|
||||
}
|
||||
makeObserver("identity-DOM-state-reset", function() {
|
||||
info("reset done");
|
||||
SimpleTest.executeSoon(next);
|
||||
});
|
||||
DOMIdentity._resetFrameState(provContext.caller);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
let steps = [
|
||||
// genKeyPair tests
|
||||
function genKeyPairExists() {
|
||||
is(typeof(identity.genKeyPair), "function",
|
||||
"Check genKeyPair is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function genKeyPairOutsideProv() {
|
||||
expectException(function(){
|
||||
identity.genKeyPair(function(){});
|
||||
}, "Check genKeyPair outside of a prov. flow");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function genKeyPairNoArgs() {
|
||||
setupProv();
|
||||
identity.beginProvisioning(function() {
|
||||
expectException(function() {
|
||||
identity.genKeyPair();
|
||||
}, "genKeyPair with no arguments");
|
||||
SimpleTest.executeSoon(resetAndNext);
|
||||
});
|
||||
},
|
||||
function genKeyPairInvalidArg() {
|
||||
setupProv();
|
||||
identity.beginProvisioning(function() {
|
||||
expectException(function() {
|
||||
identity.genKeyPair(999);
|
||||
}, "Check genKeyPair with non-function object argument");
|
||||
SimpleTest.executeSoon(resetAndNext);
|
||||
});
|
||||
},
|
||||
|
||||
// registerCertificate tests
|
||||
function registerCertificateExists() {
|
||||
is(typeof(identity.registerCertificate), "function",
|
||||
"Check registerCertificate is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function registerCertificateNoArgs() {
|
||||
setupProv();
|
||||
identity.beginProvisioning(function() {
|
||||
expectException(function() {
|
||||
identity.registerCertificate();
|
||||
}, "Check registerCertificate with no arguments");
|
||||
});
|
||||
SimpleTest.executeSoon(resetAndNext);
|
||||
},
|
||||
function registerCertificateOutsideProv() {
|
||||
expectException(function(){
|
||||
identity.registerCertificate("foo");
|
||||
}, "Check registerCertificate outside of a prov. flow");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// raiseProvisioningFailure tests
|
||||
function raiseProvisioningFailureExists() {
|
||||
is(typeof(identity.raiseProvisioningFailure), "function",
|
||||
"Check raiseProvisioningFailure is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function raiseProvisioningFailureNoArgs() {
|
||||
expectException(function() {
|
||||
identity.raiseProvisioningFailure();
|
||||
}, "raiseProvisioningFailure with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function raiseProvisioningFailureWithReason() {
|
||||
identity.raiseProvisioningFailure("my test reason");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// beginProvisioning tests
|
||||
function beginProvisioningExists() {
|
||||
is(typeof(identity.beginProvisioning), "function",
|
||||
"Check beginProvisioning is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginProvisioningNoArgs() {
|
||||
expectException(function() {
|
||||
identity.beginProvisioning();
|
||||
}, "beginProvisioning with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginProvisioningInvalidArg() {
|
||||
expectException(function() {
|
||||
identity.beginProvisioning(999);
|
||||
}, "beginProvisioning with a non-function argument");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function beginProvisioningArgs() {
|
||||
function beginProvisioningCb() {
|
||||
SimpleTest.executeSoon(resetAndNext);
|
||||
}
|
||||
is(identity.beginProvisioning(beginProvisioningCb), undefined,
|
||||
"Check minimum beginProvisioning arguments");
|
||||
},
|
||||
|
||||
finish_tests,
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(next);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,172 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for navigator.id relying party (RP) basics</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank">navigator.id RP basics</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
"use strict";
|
||||
|
||||
const RP = Cu.import("resource://gre/modules/identity/RelyingParty.jsm").RelyingParty;
|
||||
|
||||
function resetAndNext() {
|
||||
// reset DOM state for the next test
|
||||
makeObserver("identity-DOM-state-reset", function() {
|
||||
SimpleTest.executeSoon(next);
|
||||
});
|
||||
// Give the flow some time to cross the IPC boundary
|
||||
setTimeout(function() {
|
||||
let rpContext = RP._rpFlows[outerWinId];
|
||||
if (!rpContext) {
|
||||
SimpleTest.executeSoon(next);
|
||||
return;
|
||||
}
|
||||
DOMIdentity._resetFrameState(rpContext);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
let steps = [
|
||||
function nonExistentProp() {
|
||||
is(identity.foobarbaz, undefined, "Check that foobarbaz does not exist");
|
||||
expectException(function() {
|
||||
identity.foobarbaz()
|
||||
}, "Check for exception calling non-existent method", "TypeError");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// test request before watch throws an exception
|
||||
function requestBeforeWatch() {
|
||||
expectException(function() {
|
||||
identity.request();
|
||||
});
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// watch tests
|
||||
function watchExists() {
|
||||
is(typeof(identity.watch), "function", "Check watch is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function watchNoArgs() {
|
||||
expectException(function() {
|
||||
identity.watch();
|
||||
}, "watch with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function watchEmptyObj() {
|
||||
expectException(function() {
|
||||
identity.watch({});
|
||||
}, "watch with empty object argument");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function watchOnLoginBool() {
|
||||
expectException(function() {
|
||||
identity.watch({onlogin: true});
|
||||
}, "watch with invalid onlogin member");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function watchOnLoginLogoutBool() {
|
||||
expectException(function() {
|
||||
identity.watch({onlogin: true, onlogout: false});
|
||||
}, "watch with invalid onlogin and onlogout members");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function watchMinimumArgs() {
|
||||
function onLoginLogoutCb() {
|
||||
throw "onlogin/onlogout callback shouldn't have been called";
|
||||
}
|
||||
is(identity.watch({onlogin: onLoginLogoutCb, onlogout: onLoginLogoutCb}),
|
||||
undefined, "Check minimum watch argument members");
|
||||
resetAndNext();
|
||||
},
|
||||
function watchOnReadyType() {
|
||||
function onLoginLogoutCb() {
|
||||
throw "onlogin/onlogout callback shouldn't have been called";
|
||||
}
|
||||
let options = {
|
||||
onlogin: onLoginLogoutCb,
|
||||
onlogout: onLoginLogoutCb,
|
||||
onready: 999,
|
||||
}
|
||||
expectException(function() {
|
||||
identity.watch(options)
|
||||
}, "Check onready type");
|
||||
resetAndNext();
|
||||
},
|
||||
function watchLoggedInEmailType() {
|
||||
function onLoginLogoutCb() {
|
||||
throw "onlogin/onlogout callback shouldn't have been called";
|
||||
}
|
||||
let options = {
|
||||
onlogin: onLoginLogoutCb,
|
||||
onlogout: onLoginLogoutCb,
|
||||
loggedInEmail: {},
|
||||
}
|
||||
expectException(function() {
|
||||
identity.watch(options)
|
||||
}, "Check loggedInEmail type");
|
||||
resetAndNext();
|
||||
},
|
||||
function watchOnReadyCalled() {
|
||||
let onLogoutCalled = false;
|
||||
let options = {
|
||||
loggedInEmail: "loggedOut@user.com",
|
||||
onlogin: function onLoginCb(assertion) {
|
||||
throw "onlogin/onlogout callback shouldn't have been called";
|
||||
},
|
||||
onlogout: function onLogoutCb() {
|
||||
is(arguments.length, 0, "Check onlogout argument length");
|
||||
onLogoutCalled = true;
|
||||
},
|
||||
onready: function onReady() {
|
||||
is(arguments.length, 0, "Check onready argument length");
|
||||
ok(onLogoutCalled, "onlogout callback should be called before onready");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
}
|
||||
is(identity.watch(options), undefined, "Check onready is called");
|
||||
},
|
||||
|
||||
// request tests
|
||||
function requestExists() {
|
||||
is(typeof(identity.request), "function", "Check request is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function requestNoArgs() {
|
||||
is(identity.request(), undefined, "Check request with no arguments");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
function requestEmptyObj() {
|
||||
is(identity.request({}), undefined, "Check request with empty object argument");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
// logout tests
|
||||
function logoutExists() {
|
||||
is(typeof(identity.logout), "function", "Check logout is a function");
|
||||
SimpleTest.executeSoon(next);
|
||||
},
|
||||
|
||||
finish_tests,
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(next);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -42,7 +42,6 @@ function IdentityProviderService() {
|
|||
|
||||
IdentityProviderService.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
|
||||
_sandboxConfigured: false,
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
|
@ -84,14 +83,6 @@ IdentityProviderService.prototype = {
|
|||
|
||||
shutdown: function RP_shutdown() {
|
||||
this.reset();
|
||||
|
||||
if (this._sandboxConfigured) {
|
||||
// Tear down message manager listening on the hidden window
|
||||
Cu.import("resource://gre/modules/DOMIdentity.jsm");
|
||||
DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, false);
|
||||
this._sandboxConfigured = false;
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, "quit-application-granted");
|
||||
},
|
||||
|
||||
|
@ -441,14 +432,6 @@ IdentityProviderService.prototype = {
|
|||
*/
|
||||
_createProvisioningSandbox: function _createProvisioningSandbox(aURL, aCallback) {
|
||||
log("_createProvisioningSandbox:", aURL);
|
||||
|
||||
if (!this._sandboxConfigured) {
|
||||
// Configure message manager listening on the hidden window
|
||||
Cu.import("resource://gre/modules/DOMIdentity.jsm");
|
||||
DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, true);
|
||||
this._sandboxConfigured = true;
|
||||
}
|
||||
|
||||
new Sandbox(aURL, aCallback);
|
||||
},
|
||||
|
||||
|
|
|
@ -13,6 +13,6 @@ include $(DEPTH)/config/autoconf.mk
|
|||
MODULE = test_identity
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
DIRS = chrome mochitest
|
||||
DIRS = chrome
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -1,22 +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/.
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = toolkit/identity/tests/mochitest
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
head_identity.js \
|
||||
test_authentication.html \
|
||||
test_provisioning.html \
|
||||
test_relying_party.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
|
@ -1,202 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/** Helper functions for identity mochitests **/
|
||||
/** Please keep functions in-sync with unit/head_identity.js **/
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = SpecialPowers.wrap(Components).classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = SpecialPowers.wrap(Components).utils;
|
||||
|
||||
const TEST_URL = "http://mochi.test:8888";
|
||||
const TEST_URL2 = "https://myfavoritebaconinacan.com";
|
||||
const TEST_USER = "user@example.com";
|
||||
const TEST_PRIVKEY = "fake-privkey";
|
||||
const TEST_CERT = "fake-cert";
|
||||
const TEST_IDPPARAMS = {
|
||||
domain: "example.com",
|
||||
idpParams: {
|
||||
authentication: "/foo/authenticate.html",
|
||||
provisioning: "/foo/provision.html"
|
||||
},
|
||||
};
|
||||
|
||||
const Services = Cu.import("resource://gre/modules/Services.jsm").Services;
|
||||
|
||||
// Set the debug pref before loading other modules
|
||||
SpecialPowers.setBoolPref("toolkit.identity.debug", true);
|
||||
SpecialPowers.setBoolPref("dom.identity.enabled", true);
|
||||
|
||||
const jwcrypto = Cu.import("resource://gre/modules/identity/jwcrypto.jsm").jwcrypto;
|
||||
const IdentityStore = Cu.import("resource://gre/modules/identity/IdentityStore.jsm").IdentityStore;
|
||||
const RelyingParty = Cu.import("resource://gre/modules/identity/RelyingParty.jsm").RelyingParty;
|
||||
const XPCOMUtils = Cu.import("resource://gre/modules/XPCOMUtils.jsm").XPCOMUtils;
|
||||
const IDService = Cu.import("resource://gre/modules/identity/Identity.jsm").IdentityService;
|
||||
const IdentityProvider = Cu.import("resource://gre/modules/identity/IdentityProvider.jsm").IdentityProvider;
|
||||
|
||||
const identity = navigator.id || navigator.mozId;
|
||||
|
||||
function do_check_null(aVal, aMsg) {
|
||||
is(aVal, null, aMsg);
|
||||
}
|
||||
|
||||
function do_timeout(aDelay, aFunc) {
|
||||
setTimeout(aFunc, aDelay);
|
||||
}
|
||||
|
||||
function get_idstore() {
|
||||
return IdentityStore;
|
||||
}
|
||||
|
||||
// create a mock "watch" object, which the Identity Service
|
||||
function mock_watch(aIdentity, aDoFunc) {
|
||||
function partial(fn) {
|
||||
let args = Array.prototype.slice.call(arguments, 1);
|
||||
return function() {
|
||||
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
|
||||
let mockedWatch = {};
|
||||
mockedWatch.loggedInEmail = aIdentity;
|
||||
mockedWatch['do'] = aDoFunc;
|
||||
mockedWatch.onready = partial(aDoFunc, 'ready');
|
||||
mockedWatch.onlogin = partial(aDoFunc, 'login');
|
||||
mockedWatch.onlogout = partial(aDoFunc, 'logout');
|
||||
|
||||
return mockedWatch;
|
||||
}
|
||||
|
||||
// mimicking callback funtionality for ease of testing
|
||||
// this observer auto-removes itself after the observe function
|
||||
// is called, so this is meant to observe only ONE event.
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
function observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == aObserveTopic) {
|
||||
|
||||
Services.obs.removeObserver(this, aObserveTopic);
|
||||
try {
|
||||
aObserveFunc(SpecialPowers.wrap(aSubject), aTopic, aData);
|
||||
} catch (ex) {
|
||||
ok(false, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observe, aObserveTopic, false);
|
||||
}
|
||||
|
||||
// set up the ID service with an identity with keypair and all
|
||||
// when ready, invoke callback with the identity
|
||||
function setup_test_identity(identity, cert, cb) {
|
||||
// set up the store so that we're supposed to be logged in
|
||||
let store = get_idstore();
|
||||
|
||||
function keyGenerated(err, kpo) {
|
||||
store.addIdentity(identity, kpo, cert);
|
||||
cb();
|
||||
};
|
||||
|
||||
jwcrypto.generateKeyPair("DS160", keyGenerated);
|
||||
}
|
||||
|
||||
// takes a list of functions and returns a function that
|
||||
// when called the first time, calls the first func,
|
||||
// then the next time the second, etc.
|
||||
function call_sequentially() {
|
||||
let numCalls = 0;
|
||||
let funcs = arguments;
|
||||
|
||||
return function() {
|
||||
if (!funcs[numCalls]) {
|
||||
let argString = Array.prototype.slice.call(arguments).join(",");
|
||||
ok(false, "Too many calls: " + argString);
|
||||
return;
|
||||
}
|
||||
funcs[numCalls].apply(funcs[numCalls], arguments);
|
||||
numCalls += 1;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a provisioning workflow with appropriate callbacks
|
||||
*
|
||||
* identity is the email we're provisioning.
|
||||
*
|
||||
* afterSetupCallback is required.
|
||||
*
|
||||
* doneProvisioningCallback is optional, if the caller
|
||||
* wants to be notified when the whole provisioning workflow is done
|
||||
*
|
||||
* frameCallbacks is optional, contains the callbacks that the sandbox
|
||||
* frame would provide in response to DOM calls.
|
||||
*/
|
||||
function setup_provisioning(identity, afterSetupCallback, doneProvisioningCallback, callerCallbacks) {
|
||||
IDService.reset();
|
||||
|
||||
let util = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let provId = util.outerWindowID;
|
||||
IDService.IDP._provisionFlows[provId] = {
|
||||
identity : identity,
|
||||
idpParams: TEST_IDPPARAMS,
|
||||
callback: function(err) {
|
||||
if (doneProvisioningCallback)
|
||||
doneProvisioningCallback(err);
|
||||
},
|
||||
sandbox: {
|
||||
// Emulate the free() method on the iframe sandbox
|
||||
free: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
let caller = {};
|
||||
caller.id = callerCallbacks.id = provId;
|
||||
caller.doBeginProvisioningCallback = function(id, duration_s) {
|
||||
if (callerCallbacks && callerCallbacks.beginProvisioningCallback)
|
||||
callerCallbacks.beginProvisioningCallback(id, duration_s);
|
||||
};
|
||||
caller.doGenKeyPairCallback = function(pk) {
|
||||
if (callerCallbacks && callerCallbacks.genKeyPairCallback)
|
||||
callerCallbacks.genKeyPairCallback(pk);
|
||||
};
|
||||
|
||||
afterSetupCallback(callerCallbacks);
|
||||
}
|
||||
|
||||
function resetState() {
|
||||
get_idstore().reset();
|
||||
RelyingParty.reset();
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
SpecialPowers.clearUserPref("toolkit.identity.debug");
|
||||
SpecialPowers.clearUserPref("dom.identity.enabled");
|
||||
}
|
||||
|
||||
var TESTS = [];
|
||||
|
||||
function run_next_test() {
|
||||
if (!identity) {
|
||||
todo(false, "DOM API is not available. Skipping tests.");
|
||||
cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
if (TESTS.length) {
|
||||
let test = TESTS.shift();
|
||||
info(test.name);
|
||||
try {
|
||||
test();
|
||||
} catch (ex) {
|
||||
ok(false, ex);
|
||||
}
|
||||
} else {
|
||||
cleanup();
|
||||
info("all done");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Test of Identity Provider (IDP) Authentication using the DOM APIs
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test of Identity Provider (IDP) Authentication using the DOM APIs</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
</head>
|
||||
<body onload="run_next_test()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753238">Test of Identity Provider (IDP) Authentication using the DOM APIs</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test of Identity Provider (IDP) Authentication using the DOM APIs **/
|
||||
/** Most tests are ported from test_authentication.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const DOMIdentity = Cu.import("resource://gre/modules/DOMIdentity.jsm")
|
||||
.DOMIdentity;
|
||||
let outerWinId = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
|
||||
function run_next_auth_test() {
|
||||
// Reset the DOM state then run the next test
|
||||
let provContext = IdentityProvider._provisionFlows[outerWinId];
|
||||
if (provContext && provContext.caller) {
|
||||
makeObserver("identity-DOM-state-reset", function() {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
});
|
||||
DOMIdentity._resetFrameState(provContext.caller);
|
||||
} else {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
}
|
||||
}
|
||||
|
||||
function test_begin_authentication_flow() {
|
||||
let _provId = null;
|
||||
|
||||
// set up a watch, to be consistent
|
||||
let mockedDoc = mock_watch(null, function(action, params) {});
|
||||
identity.watch(mockedDoc);
|
||||
|
||||
// The identity-auth notification is sent up to the UX from the
|
||||
// _doAuthentication function. Be ready to receive it and call
|
||||
// beginAuthentication
|
||||
makeObserver("identity-auth", function (aSubject, aTopic, aData) {
|
||||
isnot(aSubject, null);
|
||||
|
||||
is(aSubject.wrappedJSObject.provId, _provId);
|
||||
|
||||
run_next_auth_test();
|
||||
});
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
_provId = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
}, function() {},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
// let's say this user needs to authenticate
|
||||
IDService.IDP._doAuthentication(_provId, TEST_IDPPARAMS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test_complete_authentication_flow() {
|
||||
let _provId = null;
|
||||
let _authId = null;
|
||||
let id = TEST_USER;
|
||||
|
||||
let callbacksFired = false;
|
||||
let topicObserved = false;
|
||||
|
||||
// The result of authentication should be a successful login
|
||||
IDService.reset();
|
||||
|
||||
setup_test_identity(id, TEST_CERT, function() {
|
||||
// When we authenticate, our ready callback will be fired.
|
||||
// At the same time, a separate topic will be sent up to the
|
||||
// the observer in the UI. The test is complete when both
|
||||
// events have occurred.
|
||||
let mockedDoc = mock_watch(null, call_sequentially(
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
|
||||
// if notification already received by observer, test is done
|
||||
callbacksFired = true;
|
||||
if (topicObserved) {
|
||||
run_next_auth_test();
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
makeObserver("identity-login-state-changed", function (aSubject, aTopic, aData) {
|
||||
info("identity-login-state-changed");
|
||||
isnot(aSubject, null);
|
||||
|
||||
//is(aSubject.wrappedJSObject.rpId, mockedDoc.id);
|
||||
is(aData, null);
|
||||
|
||||
// if callbacks in caller doc already fired, test is done.
|
||||
topicObserved = true;
|
||||
if (callbacksFired) {
|
||||
run_next_auth_test();
|
||||
}
|
||||
});
|
||||
|
||||
identity.watch(mockedDoc);
|
||||
});
|
||||
|
||||
// A mock calling context
|
||||
let authCaller = {
|
||||
doBeginAuthenticationCallback: function doBeginAuthenticationCallback(aIdentity) {
|
||||
is(aIdentity, TEST_USER);
|
||||
|
||||
identity.completeAuthentication();
|
||||
},
|
||||
|
||||
doError: function(err) {
|
||||
ok(false, "OW! My doError callback hurts!: " + err);
|
||||
},
|
||||
};
|
||||
|
||||
makeObserver("identity-auth-complete", function (aSubject, aTopic, aData) {
|
||||
is(aSubject.wrappedJSObject.identity, TEST_USER);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Create a provisioning flow for our auth flow to attach to
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(provFlow) {
|
||||
_provId = provFlow.id;
|
||||
|
||||
identity.beginProvisioning(provFlow.beginProvisioningCallback);
|
||||
}, function() {},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
// let's say this user needs to authenticate
|
||||
IDService.IDP._doAuthentication(_provId, TEST_IDPPARAMS);
|
||||
|
||||
// test_begin_authentication_flow verifies that the right
|
||||
// message is sent to the UI. So that works. Moving on,
|
||||
// the UI calls setAuthenticationFlow ...
|
||||
_authId = outerWinId;
|
||||
IDService.IDP.setAuthenticationFlow(_authId, _provId);
|
||||
|
||||
// ... then the UI calls beginAuthentication ...
|
||||
authCaller.id = _authId;
|
||||
IDService.IDP._provisionFlows[_provId].caller = authCaller;
|
||||
identity.beginAuthentication(function bac() {
|
||||
info("beginAuthentication callback");
|
||||
identity.completeAuthentication();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TESTS.push(test_begin_authentication_flow);
|
||||
TESTS.push(test_complete_authentication_flow);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,286 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Test of Identity Provider (IDP) Provisioning using the DOM APIs
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test of Identity Provider (IDP) Provisioning using the DOM APIs</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
</head>
|
||||
<body onload="run_next_test()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753238">Test of Identity Provider (IDP) Provisioning using the DOM APIs</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test of Identity Provider (IDP) Provisioning using the DOM APIs **/
|
||||
/** Most tests are ported from test_provisioning.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const DOMIdentity = Cu.import("resource://gre/modules/DOMIdentity.jsm")
|
||||
.DOMIdentity;
|
||||
let outerWinId = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
|
||||
function check_provision_flow_done(provId) {
|
||||
do_check_null(IdentityProvider._provisionFlows[provId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow specifying aProvFlow so we can reset after the _provisionFlows is cleaned up.
|
||||
*/
|
||||
function run_next_prov_test(aProvFlow) {
|
||||
// Reset the DOM state then run the next test
|
||||
let provContext = aProvFlow || IdentityProvider._provisionFlows[outerWinId];
|
||||
if (provContext && provContext.caller) {
|
||||
makeObserver("identity-DOM-state-reset", function() {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
});
|
||||
DOMIdentity._resetFrameState(provContext.caller);
|
||||
} else {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
}
|
||||
}
|
||||
|
||||
function test_begin_provisioning() {
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
// call .beginProvisioning()
|
||||
// TODO: should probably throw outside of a prov. sandbox?
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
}, function() {},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
is(email, TEST_USER);
|
||||
ok(duration_s > 0);
|
||||
ok(duration_s <= (24 * 3600));
|
||||
|
||||
run_next_prov_test();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test_raise_provisioning_failure() {
|
||||
let _callerId = null;
|
||||
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
// call .beginProvisioning()
|
||||
_callerId = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
}, function(err) {
|
||||
// this should be invoked with a populated error
|
||||
isnot(err, null);
|
||||
ok(err.indexOf("can't authenticate this email") > -1);
|
||||
|
||||
run_next_prov_test();
|
||||
},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
// raise the failure as if we can't provision this email
|
||||
identity.raiseProvisioningFailure("can't authenticate this email");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test_genkeypair_before_begin_provisioning() {
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
try {
|
||||
// call genKeyPair without beginProvisioning
|
||||
identity.genKeyPair(caller.genKeyPairCallback);
|
||||
} catch (ex) {
|
||||
ok(ex, "Caught exception for calling genKeyPair without beginProvisioning: " + ex);
|
||||
run_next_prov_test();
|
||||
}
|
||||
},
|
||||
// expect this to be called with an error
|
||||
function(err) {
|
||||
ok(false, "Shoudn't reach here as DOM code should have caught the problem");
|
||||
|
||||
run_next_prov_test();
|
||||
},
|
||||
{
|
||||
// this should not be called at all!
|
||||
genKeyPairCallback: function(pk) {
|
||||
// a test that will surely fail because we shouldn't be here.
|
||||
ok(false);
|
||||
|
||||
run_next_prov_test();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_genkeypair() {
|
||||
let _callerId = null;
|
||||
|
||||
function gkpCallback(kp) {
|
||||
isnot(kp, null);
|
||||
|
||||
// yay!
|
||||
run_next_prov_test();
|
||||
}
|
||||
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
_callerId = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
},
|
||||
function(err) {
|
||||
// should not be called!
|
||||
ok(false);
|
||||
|
||||
run_next_prov_test();
|
||||
},
|
||||
{
|
||||
beginProvisioningCallback: function(email, time_s) {
|
||||
identity.genKeyPair(gkpCallback);
|
||||
},
|
||||
genKeyPairCallback: gkpCallback,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// we've already ensured that genkeypair can't be called
|
||||
// before beginProvisioning, so this test should be enough
|
||||
// to ensure full sequential call of the 3 APIs.
|
||||
function test_register_certificate_before_genkeypair() {
|
||||
let _callerID = null;
|
||||
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
// do the right thing for beginProvisioning
|
||||
_callerID = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
},
|
||||
// expect this to be called with an error
|
||||
function(err) {
|
||||
ok(false, "Shoudn't reach here as DOM code should have caught the problem");
|
||||
|
||||
run_next_prov_test();
|
||||
},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
try {
|
||||
// now we try to register cert but no keygen has been done
|
||||
identity.registerCertificate("fake-cert");
|
||||
} catch (ex) {
|
||||
ok(ex, "Caught exception for calling genKeyPair without beginProvisioning: " + ex);
|
||||
run_next_prov_test();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_register_certificate() {
|
||||
let _callerId = null;
|
||||
let provFlow = null;
|
||||
|
||||
function gkpCallback(pk) {
|
||||
// Hold on to the provFlow so we have access to .caller to cleanup later
|
||||
provFlow = IdentityProvider._provisionFlows[outerWinId];
|
||||
|
||||
identity.registerCertificate("fake-cert-42");
|
||||
}
|
||||
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
_callerId = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
},
|
||||
function(err) {
|
||||
// we should be cool!
|
||||
do_check_null(err);
|
||||
|
||||
// check that the cert is there
|
||||
let identity = get_idstore().fetchIdentity(TEST_USER);
|
||||
isnot(identity,null);
|
||||
is(identity.cert, "fake-cert-42");
|
||||
|
||||
SimpleTest.executeSoon(function check_done() {
|
||||
// cleanup will happen after the callback is called
|
||||
check_provision_flow_done(_callerId);
|
||||
|
||||
run_next_prov_test(provFlow);
|
||||
});
|
||||
},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
identity.genKeyPair(gkpCallback);
|
||||
},
|
||||
genKeyPairCallback: gkpCallback,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_get_assertion_after_provision() {
|
||||
let _callerId = null;
|
||||
let provFlow = null;
|
||||
|
||||
function gkpCallback(pk) {
|
||||
// Hold on to the provFlow so we have access to .caller to cleanup later
|
||||
provFlow = IdentityProvider._provisionFlows[outerWinId];
|
||||
identity.registerCertificate("fake-cert-42");
|
||||
}
|
||||
|
||||
setup_provisioning(
|
||||
TEST_USER,
|
||||
function(caller) {
|
||||
_callerId = caller.id;
|
||||
identity.beginProvisioning(caller.beginProvisioningCallback);
|
||||
},
|
||||
function(err) {
|
||||
// we should be cool!
|
||||
do_check_null(err);
|
||||
|
||||
// check that the cert is there
|
||||
let identity = get_idstore().fetchIdentity(TEST_USER);
|
||||
isnot(identity,null);
|
||||
is(identity.cert, "fake-cert-42");
|
||||
|
||||
SimpleTest.executeSoon(function check_done() {
|
||||
// cleanup will happen after the callback is called
|
||||
check_provision_flow_done(_callerId);
|
||||
|
||||
run_next_prov_test(provFlow);
|
||||
});
|
||||
},
|
||||
{
|
||||
beginProvisioningCallback: function(email, duration_s) {
|
||||
identity.genKeyPair(gkpCallback);
|
||||
},
|
||||
genKeyPairCallback: gkpCallback,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TESTS.push(test_genkeypair_before_begin_provisioning);
|
||||
TESTS.push(test_begin_provisioning);
|
||||
TESTS.push(test_raise_provisioning_failure);
|
||||
TESTS.push(test_register_certificate_before_genkeypair);
|
||||
TESTS.push(test_genkeypair);
|
||||
TESTS.push(test_register_certificate);
|
||||
TESTS.push(test_get_assertion_after_provision);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,223 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Test of Relying Party (RP) using the DOM APIs
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test of Relying Party (RP) using the DOM APIs</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.8" src="head_identity.js"></script>
|
||||
</head>
|
||||
<body onload="run_next_test()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753238">Test of Relying Party (RP) using the DOM APIs</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test of Relying Party (RP) using the DOM APIs **/
|
||||
/** Most tests are ported from test_relying_party.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const DOMIdentity = Cu.import("resource://gre/modules/DOMIdentity.jsm")
|
||||
.DOMIdentity;
|
||||
let outerWinId = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
|
||||
// Reset the DOM state then run the next test
|
||||
function run_next_rp_test() {
|
||||
let rpContext = RelyingParty._rpFlows[outerWinId];
|
||||
if (rpContext) {
|
||||
makeObserver("identity-DOM-state-reset", function() {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
});
|
||||
DOMIdentity._resetFrameState(rpContext);
|
||||
} else {
|
||||
SimpleTest.executeSoon(run_next_test);
|
||||
}
|
||||
}
|
||||
|
||||
function test_watch_loggedin_ready() {
|
||||
resetState();
|
||||
|
||||
let id = TEST_USER;
|
||||
setup_test_identity(id, TEST_CERT, function() {
|
||||
let store = get_idstore();
|
||||
|
||||
// set it up so we're supposed to be logged in to TEST_URL
|
||||
store.setLoginState(TEST_URL, true, id);
|
||||
identity.watch(mock_watch(id, function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
|
||||
run_next_rp_test();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function test_watch_loggedin_login() {
|
||||
resetState();
|
||||
|
||||
let id = TEST_USER;
|
||||
setup_test_identity(id, TEST_CERT, function() {
|
||||
let store = get_idstore();
|
||||
|
||||
// set it up so we're supposed to be logged in to TEST_URL
|
||||
store.setLoginState(TEST_URL, true, id);
|
||||
|
||||
// check for first a login() call, then a ready() call
|
||||
identity.watch(mock_watch(null, call_sequentially(
|
||||
function(action, params) {
|
||||
is(action, 'login');
|
||||
isnot(params, null);
|
||||
},
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
do_check_null(params);
|
||||
|
||||
run_next_rp_test();
|
||||
}
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
function test_watch_loggedin_logout() {
|
||||
resetState();
|
||||
|
||||
let id = TEST_USER;
|
||||
let other_id = "otherid@foo.com";
|
||||
setup_test_identity(other_id, TEST_CERT, function() {
|
||||
setup_test_identity(id, TEST_CERT, function() {
|
||||
let store = get_idstore();
|
||||
|
||||
// set it up so we're supposed to be logged in to TEST_URL
|
||||
// with id, not other_id
|
||||
store.setLoginState(TEST_URL, true, id);
|
||||
|
||||
// this should cause a login with an assertion for id,
|
||||
// not for other_id
|
||||
identity.watch(mock_watch(other_id, call_sequentially(
|
||||
function(action, params) {
|
||||
is(action, 'login');
|
||||
isnot(params, null);
|
||||
},
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
do_check_null(params);
|
||||
|
||||
run_next_rp_test();
|
||||
}
|
||||
)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_watch_notloggedin_ready() {
|
||||
resetState();
|
||||
|
||||
identity.watch(mock_watch(null, function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
|
||||
run_next_rp_test();
|
||||
}));
|
||||
}
|
||||
|
||||
function test_watch_notloggedin_logout() {
|
||||
resetState();
|
||||
|
||||
identity.watch(mock_watch(TEST_USER, call_sequentially(
|
||||
function(action, params) {
|
||||
is(action, 'logout');
|
||||
is(params, undefined);
|
||||
|
||||
let store = get_idstore();
|
||||
do_check_null(store.getLoginState(TEST_URL));
|
||||
},
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
run_next_rp_test();
|
||||
}
|
||||
)));
|
||||
}
|
||||
|
||||
function test_request() {
|
||||
// set up a watch, to be consistent
|
||||
let mockedDoc = mock_watch(null, function(action, params) {
|
||||
// We're not checking anything here at the moment.
|
||||
});
|
||||
|
||||
identity.watch(mockedDoc);
|
||||
|
||||
// be ready for the UX identity-request notification
|
||||
makeObserver("identity-request", function (aSubject, aTopic, aData) {
|
||||
isnot(aSubject, null);
|
||||
|
||||
run_next_rp_test();
|
||||
});
|
||||
|
||||
identity.request();
|
||||
}
|
||||
|
||||
function test_logout() {
|
||||
resetState();
|
||||
|
||||
let id = TEST_USER;
|
||||
setup_test_identity(id, TEST_CERT, function() {
|
||||
let store = get_idstore();
|
||||
|
||||
// set it up so we're supposed to be logged in to TEST_URL
|
||||
store.setLoginState(TEST_URL, true, id);
|
||||
|
||||
let doLogout;
|
||||
let mockedDoc = mock_watch(id, call_sequentially(
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
|
||||
SimpleTest.executeSoon(doLogout);
|
||||
},
|
||||
function(action, params) {
|
||||
is(action, 'logout');
|
||||
is(params, undefined);
|
||||
},
|
||||
function(action, params) {
|
||||
is(action, 'ready');
|
||||
is(params, undefined);
|
||||
|
||||
run_next_rp_test();
|
||||
}));
|
||||
|
||||
doLogout = function() {
|
||||
makeObserver("identity-login-state-changed", function (aSubject, aTopic, aData) {
|
||||
isnot(aSubject.wrappedJSObject.rpId, null, "Check rpId is not null");
|
||||
is(aData, null, "Check identity changed to nobody");
|
||||
|
||||
ok(!store.getLoginState(TEST_URL).isLoggedIn, "Check isLoggedIn is false");
|
||||
is(store.getLoginState(TEST_URL).email, TEST_USER, "Check notification email");
|
||||
});
|
||||
identity.logout();
|
||||
};
|
||||
|
||||
identity.watch(mockedDoc);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
TESTS = TESTS.concat([test_watch_loggedin_ready, test_watch_loggedin_login, test_watch_loggedin_logout]);
|
||||
TESTS = TESTS.concat([test_watch_notloggedin_ready, test_watch_notloggedin_logout]);
|
||||
TESTS.push(test_request);
|
||||
TESTS.push(test_logout);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -10,8 +10,8 @@ tail = tail_identity.js
|
|||
[test_crypto_service.js]
|
||||
[test_identity.js]
|
||||
[test_jwcrypto.js]
|
||||
[test_observer_topics.js]
|
||||
[test_provisioning.js]
|
||||
[test_relying_party.js]
|
||||
[test_store.js]
|
||||
[test_well-known.js]
|
||||
[test_observer_topics.js]
|
||||
|
|
|
@ -875,7 +875,6 @@ if [ "$ENABLE_TESTS" ]; then
|
|||
toolkit/devtools/debugger/tests/Makefile
|
||||
toolkit/identity/tests/Makefile
|
||||
toolkit/identity/tests/chrome/Makefile
|
||||
toolkit/identity/tests/mochitest/Makefile
|
||||
toolkit/mozapps/downloads/tests/Makefile
|
||||
toolkit/mozapps/downloads/tests/chrome/Makefile
|
||||
toolkit/mozapps/extensions/test/Makefile
|
||||
|
|
Загрузка…
Ссылка в новой задаче