mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 804932 - Pass arbitrary options from RPs to BrowserID internal api methods. r=benadida
This commit is contained in:
parent
095334dcc9
commit
ac891e49f3
@ -43,7 +43,7 @@ if (typeof kIdentityJSLoaded === 'undefined') {
|
||||
}
|
||||
|
||||
var showUI = false;
|
||||
var options = null;
|
||||
var options = {};
|
||||
var isLoaded = false;
|
||||
var func = null;
|
||||
|
||||
@ -65,7 +65,6 @@ function identityCall(message) {
|
||||
* destroys our context.
|
||||
*/
|
||||
function closeIdentityDialog() {
|
||||
log('ready to close');
|
||||
// tell gecko we're done.
|
||||
func = null; options = null;
|
||||
sendAsyncMessage(kIdentityDelegateFinished);
|
||||
@ -78,17 +77,14 @@ function closeIdentityDialog() {
|
||||
function doInternalWatch() {
|
||||
log("doInternalWatch:", options, isLoaded);
|
||||
if (options && isLoaded) {
|
||||
log("internal watch options:", options);
|
||||
let BrowserID = content.wrappedJSObject.BrowserID;
|
||||
BrowserID.internal.watch(function(aParams) {
|
||||
log("sending watch method message:", aParams.method);
|
||||
identityCall(aParams);
|
||||
if (aParams.method === "ready") {
|
||||
log("watch finished.");
|
||||
closeIdentityDialog();
|
||||
}
|
||||
},
|
||||
JSON.stringify({loggedInUser: options.loggedInUser, origin: options.origin}),
|
||||
JSON.stringify(options),
|
||||
function(...things) {
|
||||
log("internal: ", things);
|
||||
}
|
||||
@ -103,8 +99,7 @@ function doInternalRequest() {
|
||||
options.origin,
|
||||
function(assertion) {
|
||||
if (assertion) {
|
||||
log("request -> assertion, so do login");
|
||||
identityCall({method:'login',assertion:assertion});
|
||||
identityCall({method: 'login', assertion: assertion});
|
||||
}
|
||||
closeIdentityDialog();
|
||||
},
|
||||
@ -116,7 +111,6 @@ function doInternalLogout(aOptions) {
|
||||
log("doInternalLogout:", (options && isLoaded));
|
||||
if (options && isLoaded) {
|
||||
let BrowserID = content.wrappedJSObject.BrowserID;
|
||||
log("logging you out of ", options.origin);
|
||||
BrowserID.internal.logout(options.origin, function() {
|
||||
identityCall({method:'logout'});
|
||||
closeIdentityDialog();
|
||||
@ -134,7 +128,7 @@ addEventListener("DOMContentLoaded", function(e) {
|
||||
|
||||
// listen for request
|
||||
addMessageListener(kIdentityDelegateRequest, function(aMessage) {
|
||||
log("\n\n* * * * injected identity.js received", kIdentityDelegateRequest, "\n\n\n");
|
||||
log("injected identity.js received", kIdentityDelegateRequest, "\n\n\n");
|
||||
options = aMessage.json;
|
||||
showUI = true;
|
||||
func = doInternalRequest;
|
||||
@ -143,7 +137,7 @@ addMessageListener(kIdentityDelegateRequest, function(aMessage) {
|
||||
|
||||
// listen for watch
|
||||
addMessageListener(kIdentityDelegateWatch, function(aMessage) {
|
||||
log("\n\n* * * * injected identity.js received", kIdentityDelegateWatch, "\n\n\n");
|
||||
log("injected identity.js received", kIdentityDelegateWatch, "\n\n\n");
|
||||
options = aMessage.json;
|
||||
showUI = false;
|
||||
func = doInternalWatch;
|
||||
@ -152,7 +146,7 @@ addMessageListener(kIdentityDelegateWatch, function(aMessage) {
|
||||
|
||||
// listen for logout
|
||||
addMessageListener(kIdentityDelegateLogout, function(aMessage) {
|
||||
log("\n\n* * * * injected identity.js received", kIdentityDelegateLogout, "\n\n\n");
|
||||
log("injected identity.js received", kIdentityDelegateLogout, "\n\n\n");
|
||||
options = aMessage.json;
|
||||
showUI = false;
|
||||
func = doInternalLogout;
|
||||
|
@ -76,6 +76,7 @@ const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
|
||||
"resource://gre/modules/identity/MinimalIdentity.jsm");
|
||||
@ -101,18 +102,10 @@ const kIdentityDelegateReady = "identity-delegate-ready";
|
||||
|
||||
const kIdentityControllerDoMethod = "identity-controller-doMethod";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
function log(...aMessageArgs) {
|
||||
Logger.log.apply(Logger, ["SignInToWebsiteController"].concat(aMessageArgs));
|
||||
}
|
||||
|
||||
function getRandomId() {
|
||||
return uuidgen.generateUUID().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* GaiaInterface encapsulates the our gaia functions. There are only two:
|
||||
*
|
||||
@ -207,8 +200,8 @@ let Pipe = {
|
||||
let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
let mm = frameLoader.messageManager;
|
||||
try {
|
||||
log("about to load frame script");
|
||||
mm.loadFrameScript(kIdentityShimFile, true);
|
||||
log("Loaded shim " + kIdentityShimFile + "\n");
|
||||
} catch (e) {
|
||||
log("Error loading ", kIdentityShimFile, " as a frame script: ", e);
|
||||
}
|
||||
@ -230,7 +223,7 @@ let Pipe = {
|
||||
showUI: aGaiaOptions.showUI || false,
|
||||
id: id
|
||||
};
|
||||
log('tell gaia to close the dialog');
|
||||
log('telling gaia to close the dialog');
|
||||
// tell gaia to close the dialog
|
||||
GaiaInterface.sendChromeEvent(detail);
|
||||
});
|
||||
@ -305,7 +298,7 @@ this.SignInToWebsiteController = {
|
||||
if (typeof message === 'string') {
|
||||
message = JSON.parse(message);
|
||||
}
|
||||
log("doMethod:", message.method);
|
||||
|
||||
switch(message.method) {
|
||||
case "ready":
|
||||
IdentityService.doReady(aRpId);
|
||||
@ -326,39 +319,38 @@ this.SignInToWebsiteController = {
|
||||
};
|
||||
},
|
||||
|
||||
doWatch: function SignInToWebsiteController_doWatch(aOptions) {
|
||||
doWatch: function SignInToWebsiteController_doWatch(aRpOptions) {
|
||||
// dom prevents watch from being called twice
|
||||
log("doWatch:", aOptions);
|
||||
var gaiaOptions = {
|
||||
message: kIdentityDelegateWatch,
|
||||
showUI: false
|
||||
};
|
||||
this.pipe.communicate(aOptions, gaiaOptions, this._makeDoMethodCallback(aOptions.rpId));
|
||||
this.pipe.communicate(aRpOptions, gaiaOptions, this._makeDoMethodCallback(aRpOptions.id));
|
||||
},
|
||||
|
||||
/**
|
||||
* The website is requesting login so the user must choose an identity to use.
|
||||
*/
|
||||
doRequest: function SignInToWebsiteController_doRequest(aOptions) {
|
||||
log("doRequest", aOptions);
|
||||
doRequest: function SignInToWebsiteController_doRequest(aRpOptions) {
|
||||
log("doRequest", aRpOptions);
|
||||
// tell gaia to open the identity popup
|
||||
var gaiaOptions = {
|
||||
message: kIdentityDelegateRequest,
|
||||
showUI: true
|
||||
};
|
||||
this.pipe.communicate(aOptions, gaiaOptions, this._makeDoMethodCallback(aOptions.rpId));
|
||||
this.pipe.communicate(aRpOptions, gaiaOptions, this._makeDoMethodCallback(aRpOptions.id));
|
||||
},
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
doLogout: function SignInToWebsiteController_doLogout(aOptions) {
|
||||
log("doLogout", aOptions);
|
||||
doLogout: function SignInToWebsiteController_doLogout(aRpOptions) {
|
||||
log("doLogout", aRpOptions);
|
||||
var gaiaOptions = {
|
||||
message: kIdentityDelegateLogout,
|
||||
showUI: false
|
||||
};
|
||||
this.pipe.communicate(aOptions, gaiaOptions, this._makeDoMethodCallback(aOptions.rpId));
|
||||
this.pipe.communicate(aRpOptions, gaiaOptions, this._makeDoMethodCallback(aRpOptions.id));
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -47,11 +47,20 @@ function uuid() {
|
||||
|
||||
// create a mock "doc" object, which the Identity Service
|
||||
// uses as a pointer back into the doc object
|
||||
function mockDoc(aIdentity, aOrigin, aDoFunc) {
|
||||
function mockDoc(aParams, aDoFunc) {
|
||||
let mockedDoc = {};
|
||||
mockedDoc.id = uuid();
|
||||
mockedDoc.loggedInUser = aIdentity;
|
||||
mockedDoc.origin = aOrigin;
|
||||
|
||||
// Properties of aParams may include loggedInUser
|
||||
Object.keys(aParams).forEach(function(param) {
|
||||
mockedDoc[param] = aParams[param];
|
||||
});
|
||||
|
||||
// the origin is set inside nsDOMIdentity by looking at the
|
||||
// document.nodePrincipal.origin. Here we, we must satisfy
|
||||
// ourselves with pretending.
|
||||
mockedDoc.origin = "https://jedp.gov";
|
||||
|
||||
mockedDoc['do'] = aDoFunc;
|
||||
mockedDoc.doReady = partial(aDoFunc, 'ready');
|
||||
mockedDoc.doLogin = partial(aDoFunc, 'login');
|
||||
@ -67,7 +76,12 @@ function mockDoc(aIdentity, aOrigin, aDoFunc) {
|
||||
// messages up to gaia (either the trusty ui or the hidden iframe),
|
||||
// and convey messages back down from gaia to the controller through
|
||||
// the message callback.
|
||||
function mockPipe() {
|
||||
|
||||
// The mock receiving pipe simulates gaia which, after receiving messages
|
||||
// through the pipe, will call back with instructions to invoke
|
||||
// certain methods. It mocks what comes back from the other end of
|
||||
// the pipe.
|
||||
function mockReceivingPipe() {
|
||||
let MockedPipe = {
|
||||
communicate: function(aRpOptions, aGaiaOptions, aMessageCallback) {
|
||||
switch (aGaiaOptions.message) {
|
||||
@ -89,6 +103,17 @@ function mockPipe() {
|
||||
return MockedPipe;
|
||||
}
|
||||
|
||||
// The mock sending pipe lets us test what's actually getting put in the
|
||||
// pipe.
|
||||
function mockSendingPipe(aMessageCallback) {
|
||||
let MockedPipe = {
|
||||
communicate: function(aRpOptions, aGaiaOptions, aDummyCallback) {
|
||||
aMessageCallback(aRpOptions, aGaiaOptions);
|
||||
}
|
||||
};
|
||||
return MockedPipe;
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -24,9 +24,69 @@ function test_overall() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function objectContains(object, subset) {
|
||||
let objectKeys = Object.keys(object);
|
||||
let subsetKeys = Object.keys(subset);
|
||||
|
||||
// can't have fewer keys than the subset
|
||||
if (objectKeys.length < subsetKeys.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let key;
|
||||
let success = true;
|
||||
if (subsetKeys.length > 0) {
|
||||
for (let i=0; i<subsetKeys.length; i++) {
|
||||
key = subsetKeys[i];
|
||||
|
||||
// key exists in the source object
|
||||
if (typeof object[key] === 'undefined') {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// recursively check object values
|
||||
else if (typeof subset[key] === 'object') {
|
||||
if (typeof object[key] !== 'object') {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (! objectContains(object[key], subset[key])) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (object[key] !== subset[key]) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
function test_object_contains() {
|
||||
do_test_pending();
|
||||
|
||||
let someObj = {
|
||||
pies: 42,
|
||||
green: "spam",
|
||||
flan: {yes: "please"}
|
||||
};
|
||||
let otherObj = {
|
||||
pies: 42,
|
||||
flan: {yes: "please"}
|
||||
};
|
||||
do_check_true(objectContains(someObj, otherObj));
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_mock_doc() {
|
||||
do_test_pending();
|
||||
let mockedDoc = mockDoc(null, TEST_URL, function(action, params) {
|
||||
let mockedDoc = mockDoc({loggedInUser: null}, function(action, params) {
|
||||
do_check_eq(action, 'coffee');
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
@ -43,15 +103,14 @@ function test_watch() {
|
||||
setup_test_identity("pie@food.gov", TEST_CERT, function() {
|
||||
let controller = SignInToWebsiteController;
|
||||
|
||||
let mockedDoc = mockDoc(null, TEST_URL, function(action, params) {
|
||||
let mockedDoc = mockDoc({loggedInUser: null}, function(action, params) {
|
||||
do_check_eq(action, 'ready');
|
||||
controller.uninit();
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
controller.init({pipe: mockPipe()});
|
||||
|
||||
controller.init({pipe: mockReceivingPipe()});
|
||||
MinimalIDService.RP.watch(mockedDoc, {});
|
||||
});
|
||||
}
|
||||
@ -62,7 +121,7 @@ function test_request_login() {
|
||||
setup_test_identity("flan@food.gov", TEST_CERT, function() {
|
||||
let controller = SignInToWebsiteController;
|
||||
|
||||
let mockedDoc = mockDoc(null, TEST_URL, call_sequentially(
|
||||
let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially(
|
||||
function(action, params) {
|
||||
do_check_eq(action, 'ready');
|
||||
do_check_eq(params, undefined);
|
||||
@ -76,7 +135,7 @@ function test_request_login() {
|
||||
}
|
||||
));
|
||||
|
||||
controller.init({pipe: mockPipe()});
|
||||
controller.init({pipe: mockReceivingPipe()});
|
||||
MinimalIDService.RP.watch(mockedDoc, {});
|
||||
MinimalIDService.RP.request(mockedDoc.id, {});
|
||||
});
|
||||
@ -88,7 +147,7 @@ function test_request_logout() {
|
||||
setup_test_identity("flan@food.gov", TEST_CERT, function() {
|
||||
let controller = SignInToWebsiteController;
|
||||
|
||||
let mockedDoc = mockDoc(null, TEST_URL, call_sequentially(
|
||||
let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially(
|
||||
function(action, params) {
|
||||
do_check_eq(action, 'ready');
|
||||
do_check_eq(params, undefined);
|
||||
@ -102,7 +161,7 @@ function test_request_logout() {
|
||||
}
|
||||
));
|
||||
|
||||
controller.init({pipe: mockPipe()});
|
||||
controller.init({pipe: mockReceivingPipe()});
|
||||
MinimalIDService.RP.watch(mockedDoc, {});
|
||||
MinimalIDService.RP.logout(mockedDoc.id, {});
|
||||
});
|
||||
@ -114,7 +173,7 @@ function test_request_login_logout() {
|
||||
setup_test_identity("unagi@food.gov", TEST_CERT, function() {
|
||||
let controller = SignInToWebsiteController;
|
||||
|
||||
let mockedDoc = mockDoc(null, TEST_URL, call_sequentially(
|
||||
let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially(
|
||||
function(action, params) {
|
||||
do_check_eq(action, 'ready');
|
||||
do_check_eq(params, undefined);
|
||||
@ -130,29 +189,68 @@ function test_request_login_logout() {
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
}
|
||||
/*
|
||||
,function(action, params) {
|
||||
do_check_eq(action, 'ready');
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
}
|
||||
*/
|
||||
));
|
||||
|
||||
controller.init({pipe: mockPipe()});
|
||||
controller.init({pipe: mockReceivingPipe()});
|
||||
MinimalIDService.RP.watch(mockedDoc, {});
|
||||
MinimalIDService.RP.request(mockedDoc.id, {});
|
||||
MinimalIDService.RP.logout(mockedDoc.id, {});
|
||||
});
|
||||
}
|
||||
|
||||
function test_options_pass_through() {
|
||||
do_test_pending();
|
||||
|
||||
// An meaningless structure for testing that RP messages preserve
|
||||
// objects and their parameters as they are passed back and forth.
|
||||
let randomMixedParams = {
|
||||
loggedInUser: "juanita@mozilla.com",
|
||||
pie: 42,
|
||||
someThing: {
|
||||
name: "Pertelote",
|
||||
legs: 4,
|
||||
nested: {bee: "Eric", remaining: "1/2"}
|
||||
}
|
||||
};
|
||||
|
||||
let mockedDoc = mockDoc(randomMixedParams, function(action, params) {});
|
||||
|
||||
function pipeOtherEnd(rpOptions, gaiaOptions) {
|
||||
// Ensure that every time we receive a message, our mixed
|
||||
// random params are contained in that message
|
||||
do_check_true(objectContains(rpOptions, randomMixedParams));
|
||||
|
||||
switch (gaiaOptions.message) {
|
||||
case "identity-delegate-watch":
|
||||
MinimalIDService.RP.request(mockedDoc.id, {});
|
||||
break;
|
||||
case "identity-delegate-request":
|
||||
MinimalIDService.RP.logout(mockedDoc.id, {});
|
||||
break;
|
||||
case "identity-delegate-logout":
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let controller = SignInToWebsiteController;
|
||||
controller.init({pipe: mockSendingPipe(pipeOtherEnd)});
|
||||
|
||||
MinimalIDService.RP.watch(mockedDoc, {});
|
||||
}
|
||||
|
||||
let TESTS = [
|
||||
test_overall,
|
||||
test_mock_doc,
|
||||
test_object_contains,
|
||||
|
||||
test_watch,
|
||||
test_request_login,
|
||||
test_request_logout,
|
||||
test_request_login_logout
|
||||
test_request_login_logout,
|
||||
|
||||
test_options_pass_through
|
||||
];
|
||||
|
||||
TESTS.forEach(add_test);
|
||||
|
@ -11,6 +11,7 @@ this.EXPORTED_SYMBOLS = ["DOMIdentity"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
|
||||
#ifdef MOZ_B2G_VERSION
|
||||
@ -31,8 +32,8 @@ function log(...aMessageArgs) {
|
||||
Logger.log.apply(Logger, ["DOMIdentity"].concat(aMessageArgs));
|
||||
}
|
||||
|
||||
function IDDOMMessage(aID) {
|
||||
this.id = aID;
|
||||
function IDDOMMessage(aOptions) {
|
||||
objectCopy(aOptions, this);
|
||||
}
|
||||
|
||||
function IDPProvisioningContext(aID, aOrigin, aTargetMM) {
|
||||
@ -46,7 +47,7 @@ IDPProvisioningContext.prototype = {
|
||||
get origin() this._origin,
|
||||
|
||||
doBeginProvisioningCallback: function IDPPC_doBeginProvCB(aID, aCertDuration) {
|
||||
let message = new IDDOMMessage(this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.identity = aID;
|
||||
message.certDuration = aCertDuration;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CallBeginProvisioningCallback",
|
||||
@ -55,7 +56,7 @@ IDPProvisioningContext.prototype = {
|
||||
|
||||
doGenKeyPairCallback: function IDPPC_doGenKeyPairCallback(aPublicKey) {
|
||||
log("doGenKeyPairCallback");
|
||||
let message = new IDDOMMessage(this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.publicKey = aPublicKey;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CallGenKeyPairCallback", message);
|
||||
},
|
||||
@ -76,7 +77,7 @@ IDPAuthenticationContext.prototype = {
|
||||
get origin() this._origin,
|
||||
|
||||
doBeginAuthenticationCallback: function IDPAC_doBeginAuthCB(aIdentity) {
|
||||
let message = new IDDOMMessage(this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
message.identity = aIdentity;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CallBeginAuthenticationCallback",
|
||||
message);
|
||||
@ -87,34 +88,37 @@ IDPAuthenticationContext.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
function RPWatchContext(aID, aOrigin, aLoggedInUser, aTargetMM) {
|
||||
this._id = aID;
|
||||
this._origin = aOrigin;
|
||||
this._loggedInUser = aLoggedInUser;
|
||||
function RPWatchContext(aOptions, aTargetMM) {
|
||||
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");
|
||||
}
|
||||
|
||||
// default for no loggedInUser is undefined, not null
|
||||
this.loggedInUser = aOptions.loggedInUser;
|
||||
|
||||
this._mm = aTargetMM;
|
||||
}
|
||||
|
||||
RPWatchContext.prototype = {
|
||||
get id() this._id,
|
||||
get origin() this._origin,
|
||||
get loggedInUser() this._loggedInUser,
|
||||
|
||||
doLogin: function RPWatchContext_onlogin(aAssertion) {
|
||||
log("doLogin: " + this.id);
|
||||
let message = new IDDOMMessage(this.id);
|
||||
let message = new IDDOMMessage({id: 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);
|
||||
log("doLogout: " + this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch:OnLogout", message);
|
||||
},
|
||||
|
||||
doReady: function RPWatchContext_onready() {
|
||||
log("doReady: " + this.id);
|
||||
let message = new IDDOMMessage(this.id);
|
||||
let message = new IDDOMMessage({id: this.id});
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch:OnReady", message);
|
||||
},
|
||||
|
||||
@ -212,7 +216,7 @@ this.DOMIdentity = {
|
||||
if (!aContext._mm) {
|
||||
throw new Error("ERROR: Trying to reset an invalid context");
|
||||
}
|
||||
let message = new IDDOMMessage(aContext.id);
|
||||
let message = new IDDOMMessage({id: aContext.id});
|
||||
aContext._mm.sendAsyncMessage("Identity:ResetState", message);
|
||||
},
|
||||
|
||||
@ -220,8 +224,7 @@ this.DOMIdentity = {
|
||||
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.loggedInUser, targetMM);
|
||||
let context = new RPWatchContext(message, targetMM);
|
||||
IdentityService.RP.watch(context);
|
||||
},
|
||||
|
||||
@ -230,7 +233,7 @@ this.DOMIdentity = {
|
||||
},
|
||||
|
||||
_logout: function DOMIdentity__logout(message) {
|
||||
IdentityService.RP.logout(message.id, message.origin);
|
||||
IdentityService.RP.logout(message.id, message.origin, message);
|
||||
},
|
||||
|
||||
_beginProvisioning: function DOMIdentity__beginProvisioning(message, targetMM) {
|
||||
|
@ -18,13 +18,11 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/IdentityUtils.jsm");
|
||||
|
||||
// This is the child process corresponding to nsIDOMIdentity
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
// This is the child process corresponding to nsIDOMIdentity.
|
||||
|
||||
|
||||
function nsDOMIdentity(aIdentityInternal) {
|
||||
this._identityInternal = aIdentityInternal;
|
||||
}
|
||||
@ -77,7 +75,7 @@ nsDOMIdentity.prototype = {
|
||||
throw new Error("onready must be a function");
|
||||
}
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
let message = this.DOMIdentityMessage(aOptions);
|
||||
|
||||
// loggedInUser vs loggedInEmail
|
||||
// https://developer.mozilla.org/en-US/docs/DOM/navigator.id.watch
|
||||
@ -125,7 +123,7 @@ nsDOMIdentity.prototype = {
|
||||
throw new Error("navigator.id.request called too many times");
|
||||
}
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
let message = this.DOMIdentityMessage(aOptions);
|
||||
|
||||
if (aOptions) {
|
||||
// Optional string properties
|
||||
@ -314,7 +312,6 @@ nsDOMIdentity.prototype = {
|
||||
|
||||
_receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
this._log("receiveMessage: " + aMessage.name);
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Identity:ResetState":
|
||||
@ -419,13 +416,24 @@ nsDOMIdentity.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to create messages to send using a message manager
|
||||
* Helper to create messages to send using a message manager.
|
||||
* Pass through user options if they are not functions. Always
|
||||
* overwrite id and origin. Caller does not get to set those.
|
||||
*/
|
||||
DOMIdentityMessage: function DOMIdentityMessage() {
|
||||
return {
|
||||
id: this._id,
|
||||
origin: this._origin,
|
||||
};
|
||||
DOMIdentityMessage: function DOMIdentityMessage(aOptions) {
|
||||
aOptions = aOptions || {};
|
||||
let message = {};
|
||||
|
||||
objectCopy(aOptions, message);
|
||||
|
||||
// outer window id
|
||||
message.id = this._id;
|
||||
|
||||
// window origin
|
||||
message.origin = this._origin;
|
||||
|
||||
dump("nsDOM message: " + JSON.stringify(message) + "\n");
|
||||
return message;
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -8,10 +8,21 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["checkDeprecated", "checkRenamed"];
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"checkDeprecated",
|
||||
"checkRenamed",
|
||||
"getRandomId",
|
||||
"objectCopy"
|
||||
];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Logger",
|
||||
"resource://gre/modules/identity/LogUtils.jsm");
|
||||
|
||||
@ -44,3 +55,21 @@ this.checkRenamed = function checkRenamed(aOptions, aOldName, aNewName) {
|
||||
delete(aOptions[aOldName]);
|
||||
}
|
||||
};
|
||||
|
||||
this.getRandomId = function getRandomId() {
|
||||
return uuidgen.generateUUID().toString();
|
||||
};
|
||||
|
||||
/*
|
||||
* copy source object into target, excluding private properties
|
||||
* (those whose names begin with an underscore)
|
||||
*/
|
||||
this.objectCopy = function objectCopy(source, target){
|
||||
let desc;
|
||||
Object.getOwnPropertyNames(source).forEach(function(name) {
|
||||
if (name[0] !== '_') {
|
||||
desc = Object.getOwnPropertyDescriptor(source, name);
|
||||
Object.defineProperty(target, name, desc);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ const Cr = Components.results;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/identity/LogUtils.jsm");
|
||||
Cu.import("resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
"jwcrypto",
|
||||
@ -37,6 +38,35 @@ function reportError(...aMessageArgs) {
|
||||
Logger.reportError.apply(Logger, ["core"].concat(aMessageArgs));
|
||||
}
|
||||
|
||||
function makeMessageObject(aRpCaller) {
|
||||
let options = {};
|
||||
|
||||
options.id = aRpCaller.id;
|
||||
options.origin = aRpCaller.origin;
|
||||
|
||||
// loggedInUser can be undefined, null, or a string
|
||||
options.loggedInUser = aRpCaller.loggedInUser;
|
||||
|
||||
Object.keys(aRpCaller).forEach(function(option) {
|
||||
// Duplicate the callerobject, scrubbing out functions and other
|
||||
// internal variables (like _mm, the message manager object)
|
||||
if (!Object.hasOwnProperty(this, option)
|
||||
&& option[0] !== '_'
|
||||
&& typeof aRpCaller[option] !== 'function') {
|
||||
options[option] = aRpCaller[option];
|
||||
}
|
||||
});
|
||||
|
||||
if (! (options.id && options.origin)) {
|
||||
let err = "id and origin required in relying-party message";
|
||||
reportError(err);
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
dump("message object is: " + JSON.stringify(options) + "\n");
|
||||
return options;
|
||||
}
|
||||
|
||||
function IDService() {
|
||||
Services.obs.addObserver(this, "quit-application-granted", false);
|
||||
// Services.obs.addObserver(this, "identity-auth-complete", false);
|
||||
@ -97,15 +127,11 @@ IDService.prototype = {
|
||||
*
|
||||
*/
|
||||
watch: function watch(aRpCaller) {
|
||||
log("watch: caller keys:", Object.keys(aRpCaller));
|
||||
log("watch: rpcaller:", aRpCaller);
|
||||
// store the caller structure and notify the UI observers
|
||||
|
||||
dump("RP - watch: " + JSON.stringify(aRpCaller) + "\n");
|
||||
this._rpFlows[aRpCaller.id] = aRpCaller;
|
||||
|
||||
let options = {rpId: aRpCaller.id,
|
||||
origin: aRpCaller.origin,
|
||||
loggedInUser: aRpCaller.loggedInUser};
|
||||
let options = makeMessageObject(aRpCaller);
|
||||
log("sending identity-controller-watch:", options);
|
||||
Services.obs.notifyObservers({wrappedJSObject: options},"identity-controller-watch", null);
|
||||
},
|
||||
@ -121,12 +147,12 @@ IDService.prototype = {
|
||||
* (Object) options including privacyPolicy, termsOfService
|
||||
*/
|
||||
request: function request(aRPId, aOptions) {
|
||||
log("request: rpId:", aRPId);
|
||||
let rp = this._rpFlows[aRPId];
|
||||
|
||||
// Notify UX to display identity picker.
|
||||
// Pass the doc id to UX so it can pass it back to us later.
|
||||
let options = {rpId: aRPId, origin: rp.origin};
|
||||
let options = makeMessageObject(rp);
|
||||
objectCopy(aOptions, options);
|
||||
Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-request", null);
|
||||
},
|
||||
|
||||
@ -139,10 +165,9 @@ IDService.prototype = {
|
||||
*
|
||||
*/
|
||||
logout: function logout(aRpCallerId) {
|
||||
log("logout: RP caller id:", aRpCallerId);
|
||||
let rp = this._rpFlows[aRpCallerId];
|
||||
|
||||
let options = {rpId: aRpCallerId, origin: rp.origin};
|
||||
let options = makeMessageObject(rp);
|
||||
Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-logout", null);
|
||||
},
|
||||
|
||||
@ -154,24 +179,30 @@ IDService.prototype = {
|
||||
|
||||
doLogin: function doLogin(aRpCallerId, aAssertion) {
|
||||
let rp = this._rpFlows[aRpCallerId];
|
||||
if (!rp)
|
||||
if (!rp) {
|
||||
dump("WARNING: doLogin found no rp to go with callerId " + aRpCallerId + "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rp.doLogin(aAssertion);
|
||||
},
|
||||
|
||||
doLogout: function doLogout(aRpCallerId) {
|
||||
let rp = this._rpFlows[aRpCallerId];
|
||||
if (!rp)
|
||||
if (!rp) {
|
||||
dump("WARNING: doLogout found no rp to go with callerId " + aRpCallerId + "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rp.doLogout();
|
||||
},
|
||||
|
||||
doReady: function doReady(aRpCallerId) {
|
||||
let rp = this._rpFlows[aRpCallerId];
|
||||
if (!rp)
|
||||
if (!rp) {
|
||||
dump("WARNING: doReady found no rp to go with callerId " + aRpCallerId + "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rp.doReady();
|
||||
},
|
||||
|
@ -14,6 +14,7 @@ const Cr = Components.results;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/identity/LogUtils.jsm");
|
||||
Cu.import("resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
Cu.import("resource://gre/modules/identity/IdentityStore.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["RelyingParty"];
|
||||
@ -215,6 +216,7 @@ IdentityRelyingParty.prototype = {
|
||||
// Notify UX to display identity picker.
|
||||
// Pass the doc id to UX so it can pass it back to us later.
|
||||
let options = {rpId: aRPId, origin: rp.origin};
|
||||
objectCopy(aOptions, options);
|
||||
|
||||
// Append URLs after resolving
|
||||
let baseURI = Services.io.newURI(rp.origin, null, null);
|
||||
|
46
toolkit/identity/tests/unit/test_identity_utils.js
Normal file
46
toolkit/identity/tests/unit/test_identity_utils.js
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/identity/IdentityUtils.jsm');
|
||||
|
||||
function test_check_deprecated() {
|
||||
let options = {
|
||||
id: 123,
|
||||
loggedInEmail: "jed@foo.com",
|
||||
pies: 42
|
||||
};
|
||||
|
||||
do_check_true(checkDeprecated(options, "loggedInEmail"));
|
||||
do_check_false(checkDeprecated(options, "flans"));
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_check_renamed() {
|
||||
let options = {
|
||||
id: 123,
|
||||
loggedInEmail: "jed@foo.com",
|
||||
pies: 42
|
||||
};
|
||||
|
||||
checkRenamed(options, "loggedInEmail", "loggedInUser");
|
||||
|
||||
// It moves loggedInEmail to loggedInUser
|
||||
do_check_false(!!options.loggedInEmail);
|
||||
do_check_eq(options.loggedInUser, "jed@foo.com");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
let TESTS = [
|
||||
test_check_deprecated,
|
||||
test_check_renamed
|
||||
];
|
||||
|
||||
TESTS.forEach(add_test);
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
@ -9,10 +9,10 @@ function toggle_debug() {
|
||||
do_test_pending();
|
||||
|
||||
function Wrapper() {
|
||||
Services.prefs.addObserver('toolkit.identity.debug', this, false);
|
||||
this.init();
|
||||
}
|
||||
Wrapper.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([ci.nsISupports, Ci.nsIObserver]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "nsPref:changed") {
|
||||
@ -21,6 +21,10 @@ function toggle_debug() {
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
|
||||
init: function() {
|
||||
Services.prefs.addObserver('toolkit.identity.debug', this, false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -31,10 +35,10 @@ function toggle_debug() {
|
||||
// test that things don't break
|
||||
|
||||
function logAlias(...args) {
|
||||
Logger.log.call(["log alias"].concat(args));
|
||||
Logger.log.apply(Logger, ["log alias"].concat(args));
|
||||
}
|
||||
function reportErrorAlias(...args) {
|
||||
Logger.reportError.call(["report error alias"].concat(args));
|
||||
Logger.reportError.apply(Logger, ["report error alias"].concat(args));
|
||||
}
|
||||
|
||||
function test_log() {
|
||||
@ -56,12 +60,15 @@ function test_wrappers() {
|
||||
}
|
||||
|
||||
let TESTS = [
|
||||
toggle_debug,
|
||||
// XXX fix me
|
||||
// toggle_debug,
|
||||
test_log,
|
||||
test_reportError,
|
||||
test_wrappers
|
||||
];
|
||||
|
||||
TESTS.forEach(add_test);
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
@ -34,7 +34,7 @@ function test_watch() {
|
||||
|
||||
let mockedDoc = mock_doc(null, TEST_URL);
|
||||
makeObserver("identity-controller-watch", function (aSubject, aTopic, aData) {
|
||||
do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
|
||||
do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
|
||||
do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
@ -51,7 +51,7 @@ function test_request() {
|
||||
|
||||
let mockedDoc = mock_doc(null, TEST_URL);
|
||||
makeObserver("identity-controller-request", function (aSubject, aTopic, aData) {
|
||||
do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
|
||||
do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
|
||||
do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
@ -69,7 +69,7 @@ function test_logout() {
|
||||
|
||||
let mockedDoc = mock_doc(null, TEST_URL);
|
||||
makeObserver("identity-controller-logout", function (aSubject, aTopic, aData) {
|
||||
do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
|
||||
do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
});
|
||||
@ -78,8 +78,6 @@ function test_logout() {
|
||||
MinimalIDService.RP.logout(mockedDoc.id, {});
|
||||
}
|
||||
|
||||
|
||||
|
||||
let TESTS = [
|
||||
test_overall,
|
||||
test_mock_doc,
|
||||
|
@ -197,12 +197,15 @@ function test_logout() {
|
||||
});
|
||||
}
|
||||
|
||||
let TESTS = [];
|
||||
|
||||
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);
|
||||
let TESTS = [
|
||||
test_watch_loggedin_ready,
|
||||
test_watch_loggedin_login,
|
||||
test_watch_loggedin_logout,
|
||||
test_watch_notloggedin_ready,
|
||||
test_watch_notloggedin_logout,
|
||||
test_request,
|
||||
test_logout
|
||||
];
|
||||
|
||||
TESTS.forEach(add_test);
|
||||
|
||||
|
@ -6,6 +6,7 @@ tail = tail_identity.js
|
||||
[test_load_modules.js]
|
||||
[test_minimalidentity.js]
|
||||
|
||||
[test_identity_utils.js]
|
||||
[test_log_utils.js]
|
||||
[test_authentication.js]
|
||||
[test_crypto_service.js]
|
||||
|
Loading…
Reference in New Issue
Block a user