summaryrefslogtreecommitdiff
path: root/toolkit/identity/tests/unit/head_identity.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/identity/tests/unit/head_identity.js')
-rw-r--r--toolkit/identity/tests/unit/head_identity.js256
1 files changed, 256 insertions, 0 deletions
diff --git a/toolkit/identity/tests/unit/head_identity.js b/toolkit/identity/tests/unit/head_identity.js
new file mode 100644
index 0000000000..a266e7aeeb
--- /dev/null
+++ b/toolkit/identity/tests/unit/head_identity.js
@@ -0,0 +1,256 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+var Cr = Components.results;
+
+Cu.import("resource://testing-common/httpd.js");
+
+// XXX until bug 937114 is fixed
+Cu.importGlobalProperties(["atob"]);
+
+// The following boilerplate makes sure that XPCOM calls
+// that use the profile directory work.
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
+ "resource://gre/modules/identity/jwcrypto.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "IDService",
+ "resource://gre/modules/identity/Identity.jsm",
+ "IdentityService");
+
+XPCOMUtils.defineLazyModuleGetter(this,
+ "IdentityStore",
+ "resource://gre/modules/identity/IdentityStore.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this,
+ "Logger",
+ "resource://gre/modules/identity/LogUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this,
+ "uuidGenerator",
+ "@mozilla.org/uuid-generator;1",
+ "nsIUUIDGenerator");
+
+const TEST_MESSAGE_MANAGER = "Mr McFeeley";
+const TEST_URL = "https://myfavoritebacon.com";
+const TEST_URL2 = "https://myfavoritebaconinacan.com";
+const TEST_USER = "user@mozilla.com";
+const TEST_PRIVKEY = "fake-privkey";
+const TEST_CERT = "fake-cert";
+const TEST_ASSERTION = "fake-assertion";
+const TEST_IDPPARAMS = {
+ domain: "myfavoriteflan.com",
+ authentication: "/foo/authenticate.html",
+ provisioning: "/foo/provision.html"
+};
+
+// The following are utility functions for Identity testing
+
+function log(...aMessageArgs) {
+ Logger.log.apply(Logger, ["test"].concat(aMessageArgs));
+}
+
+function get_idstore() {
+ return IdentityStore;
+}
+
+function partial(fn) {
+ let args = Array.prototype.slice.call(arguments, 1);
+ return function() {
+ return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
+ };
+}
+
+function uuid() {
+ return uuidGenerator.generateUUID().toString();
+}
+
+function base64UrlDecode(s) {
+ s = s.replace(/-/g, "+");
+ s = s.replace(/_/g, "/");
+
+ // Replace padding if it was stripped by the sender.
+ // See http://tools.ietf.org/html/rfc4648#section-4
+ switch (s.length % 4) {
+ case 0:
+ break; // No pad chars in this case
+ case 2:
+ s += "==";
+ break; // Two pad chars
+ case 3:
+ s += "=";
+ break; // One pad char
+ default:
+ throw new InputException("Illegal base64url string!");
+ }
+
+ // With correct padding restored, apply the standard base64 decoder
+ return atob(s);
+}
+
+// create a mock "doc" object, which the Identity Service
+// uses as a pointer back into the doc object
+function mock_doc(aIdentity, aOrigin, aDoFunc) {
+ let mockedDoc = {};
+ mockedDoc.id = uuid();
+ mockedDoc.loggedInUser = aIdentity;
+ mockedDoc.origin = aOrigin;
+ mockedDoc["do"] = aDoFunc;
+ mockedDoc._mm = TEST_MESSAGE_MANAGER;
+ mockedDoc.doReady = partial(aDoFunc, "ready");
+ mockedDoc.doLogin = partial(aDoFunc, "login");
+ mockedDoc.doLogout = partial(aDoFunc, "logout");
+ mockedDoc.doError = partial(aDoFunc, "error");
+ mockedDoc.doCancel = partial(aDoFunc, "cancel");
+ mockedDoc.doCoffee = partial(aDoFunc, "coffee");
+ mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown");
+
+ mockedDoc.RP = mockedDoc;
+
+ return mockedDoc;
+}
+
+function mock_fxa_rp(aIdentity, aOrigin, aDoFunc) {
+ let mockedDoc = {};
+ mockedDoc.id = uuid();
+ mockedDoc.emailHint = aIdentity;
+ mockedDoc.origin = aOrigin;
+ mockedDoc.wantIssuer = "firefox-accounts";
+ mockedDoc._mm = TEST_MESSAGE_MANAGER;
+
+ mockedDoc.doReady = partial(aDoFunc, "ready");
+ mockedDoc.doLogin = partial(aDoFunc, "login");
+ mockedDoc.doLogout = partial(aDoFunc, "logout");
+ mockedDoc.doError = partial(aDoFunc, "error");
+ mockedDoc.doCancel = partial(aDoFunc, "cancel");
+ mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown");
+
+ mockedDoc.RP = mockedDoc;
+
+ return mockedDoc;
+}
+
+// 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) {
+ let observer = {
+ // nsISupports provides type management in C++
+ // nsIObserver is to be an observer
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
+
+ observe: function (aSubject, aTopic, aData) {
+ if (aTopic == aObserveTopic) {
+ aObserveFunc(aSubject, aTopic, aData);
+ Services.obs.removeObserver(observer, aObserveTopic);
+ }
+ }
+ };
+
+ Services.obs.addObserver(observer, 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(",");
+ do_throw("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 provId = uuid();
+ 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 = 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(caller);
+}
+
+// Switch debug messages on by default
+var initialPrefDebugValue = false;
+try {
+ initialPrefDebugValue = Services.prefs.getBoolPref("toolkit.identity.debug");
+} catch (noPref) {}
+Services.prefs.setBoolPref("toolkit.identity.debug", true);
+
+// Switch on firefox accounts
+var initialPrefFXAValue = false;
+try {
+ initialPrefFXAValue = Services.prefs.getBoolPref("identity.fxaccounts.enabled");
+} catch (noPref) {}
+Services.prefs.setBoolPref("identity.fxaccounts.enabled", true);
+
+// after execution, restore prefs
+do_register_cleanup(function() {
+ log("restoring prefs to their initial values");
+ Services.prefs.setBoolPref("toolkit.identity.debug", initialPrefDebugValue);
+ Services.prefs.setBoolPref("identity.fxaccounts.enabled", initialPrefFXAValue);
+});
+
+