diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index c5f5c442721..265ea4b935a 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index 63d3d7d1ef4..85911a600d7 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index 7974a8541b2..abe6863294e 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index c5f5c442721..265ea4b935a 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml
index 4df0da0532f..2da5f5250a8 100644
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index 77f7e385879..ca159c4f52c 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
- "revision": "6f63b10d567e5a8fb51bbebe5e482294427cc05d",
+ "revision": "f705a3f96020c7d7aa5ec63bf3417db29e1ab2a2",
"repo_path": "/integration/gaia-central"
}
diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml
index b6a8fa034f4..3c43b86d256 100644
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml
index 8d18abbfec7..e9cc41bd743 100644
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index 7a1364f29c2..9d13b6e19d2 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml
index 3c29f6f3f14..05e7b9625d1 100644
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/dom/apps/src/PermissionsTable.jsm b/dom/apps/src/PermissionsTable.jsm
index 87d0656d23e..dfed59b8efd 100644
--- a/dom/apps/src/PermissionsTable.jsm
+++ b/dom/apps/src/PermissionsTable.jsm
@@ -367,6 +367,17 @@ this.PermissionsTable = { geolocation: {
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION,
access: ["read", "write", "create"]
+ },
+ "firefox-accounts": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-firefox-accounts": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["firefox-accounts"]
}
};
diff --git a/dom/bluetooth/bluedroid/BluetoothSocket.cpp b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
index 0330fb27442..6b0e3d27359 100644
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -145,8 +145,7 @@ public:
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
- RemoveWatchers(READ_WATCHER | WRITE_WATCHER);
-
+ Close(); // will also remove fd from I/O loop
mShuttingDownOnIOThread = true;
}
diff --git a/dom/cellbroadcast/src/CellBroadcast.cpp b/dom/cellbroadcast/src/CellBroadcast.cpp
index 849fbb07942..7df492eb5d0 100644
--- a/dom/cellbroadcast/src/CellBroadcast.cpp
+++ b/dom/cellbroadcast/src/CellBroadcast.cpp
@@ -37,6 +37,12 @@ public:
MOZ_ASSERT(mCellBroadcast);
mCellBroadcast = nullptr;
}
+
+private:
+ ~Listener()
+ {
+ MOZ_ASSERT(!mCellBroadcast);
+ }
};
NS_IMPL_ISUPPORTS(CellBroadcast::Listener, nsICellBroadcastListener)
diff --git a/dom/icc/src/IccListener.h b/dom/icc/src/IccListener.h
index e050393877e..c152678d3db 100644
--- a/dom/icc/src/IccListener.h
+++ b/dom/icc/src/IccListener.h
@@ -21,7 +21,6 @@ public:
NS_DECL_NSIICCLISTENER
IccListener(IccManager* aIccManager, uint32_t aClientId);
- ~IccListener();
void
Shutdown();
@@ -32,6 +31,9 @@ public:
return mIcc;
}
+private:
+ ~IccListener();
+
private:
uint32_t mClientId;
// We did not setup 'mIcc' and 'mIccManager' being a participant of cycle
diff --git a/dom/icc/src/IccManager.h b/dom/icc/src/IccManager.h
index c1a1f445169..8982cb9e057 100644
--- a/dom/icc/src/IccManager.h
+++ b/dom/icc/src/IccManager.h
@@ -26,7 +26,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IccManager, DOMEventTargetHelper)
IccManager(nsPIDOMWindow* aWindow);
- ~IccManager();
void
Shutdown();
@@ -52,6 +51,9 @@ public:
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+private:
+ ~IccManager();
+
private:
nsTArray> mIccListeners;
};
diff --git a/dom/identity/DOMIdentity.jsm b/dom/identity/DOMIdentity.jsm
index 2c411ce8ad2..e6c6e4a2b02 100644
--- a/dom/identity/DOMIdentity.jsm
+++ b/dom/identity/DOMIdentity.jsm
@@ -10,6 +10,7 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const PREF_FXA_ENABLED = "identity.fxaccounts.enabled";
+const FXA_PERMISSION = "firefox-accounts";
// This is the parent process corresponding to nsDOMIdentity.
this.EXPORTED_SYMBOLS = ["DOMIdentity"];
@@ -38,6 +39,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
"nsIMessageListenerManager");
+XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
+ "@mozilla.org/permissionmanager;1",
+ "nsIPermissionManager");
+
function log(...aMessageArgs) {
Logger.log.apply(Logger, ["DOMIdentity"].concat(aMessageArgs));
}
@@ -98,7 +103,7 @@ IDPAuthenticationContext.prototype = {
}
};
-function RPWatchContext(aOptions, aTargetMM) {
+function RPWatchContext(aOptions, aTargetMM, aPrincipal) {
objectCopy(aOptions, this);
// id and origin are required
@@ -106,6 +111,8 @@ function RPWatchContext(aOptions, aTargetMM) {
throw new Error("id and origin are required for RP watch context");
}
+ this.principal = aPrincipal;
+
// default for no loggedInUser is undefined, not null
this.loggedInUser = aOptions.loggedInUser;
@@ -182,8 +189,8 @@ this.DOMIdentity = {
/*
* Create a new RPWatchContext, and update the context maps.
*/
- newContext: function(message, targetMM) {
- let context = new RPWatchContext(message, targetMM);
+ newContext: function(message, targetMM, principal) {
+ let context = new RPWatchContext(message, targetMM, principal);
this._serviceContexts.set(message.id, context);
this._mmContexts.set(targetMM, message.id);
return context;
@@ -234,6 +241,28 @@ this.DOMIdentity = {
this._mmContexts.delete(targetMM);
},
+ hasPermission: function(aMessage) {
+ // We only check that the firefox accounts permission is present in the
+ // manifest.
+ if (aMessage.json && aMessage.json.wantIssuer == "firefox-accounts") {
+ if (!aMessage.principal) {
+ return false;
+ }
+ let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(Ci.nsIScriptSecurityManager);
+ let uri = Services.io.newURI(aMessage.principal.origin, null, null);
+ let principal = secMan.getAppCodebasePrincipal(uri,
+ aMessage.principal.appId, aMessage.principal.isInBrowserElement);
+
+ let permission =
+ permissionManager.testPermissionFromPrincipal(principal,
+ FXA_PERMISSION);
+ return permission != Ci.nsIPermissionManager.UNKNOWN_ACTION &&
+ permission != Ci.nsIPermissionManager.DENY_ACTION;
+ }
+ return true;
+ },
+
// nsIMessageListener
receiveMessage: function DOMIdentity_receiveMessage(aMessage) {
let msg = aMessage.json;
@@ -242,19 +271,23 @@ this.DOMIdentity = {
// used to send replies back to the proper window.
let targetMM = aMessage.target;
+ if (!this.hasPermission(aMessage)) {
+ throw new Error("PERMISSION_DENIED");
+ }
+
switch (aMessage.name) {
// RP
case "Identity:RP:Watch":
- this._watch(msg, targetMM);
+ this._watch(msg, targetMM, aMessage.principal);
break;
case "Identity:RP:Unwatch":
this._unwatch(msg, targetMM);
break;
case "Identity:RP:Request":
- this._request(msg, targetMM);
+ this._request(msg);
break;
case "Identity:RP:Logout":
- this._logout(msg, targetMM);
+ this._logout(msg);
break;
// IDP
case "Identity:IDP:BeginProvisioning":
@@ -328,9 +361,9 @@ this.DOMIdentity = {
ppmm = null;
},
- _watch: function DOMIdentity__watch(message, targetMM) {
- log("DOMIdentity__watch: " + message.id);
- let context = this.newContext(message, targetMM);
+ _watch: function DOMIdentity__watch(message, targetMM, principal) {
+ log("DOMIdentity__watch: " + message.id + " - " + principal);
+ let context = this.newContext(message, targetMM, principal);
this.getService(message).RP.watch(context);
},
diff --git a/dom/identity/nsDOMIdentity.js b/dom/identity/nsDOMIdentity.js
index 5e4597ccb9b..a5d7d946a3f 100644
--- a/dom/identity/nsDOMIdentity.js
+++ b/dom/identity/nsDOMIdentity.js
@@ -40,8 +40,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
const ERRORS = {
- "ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS":
- "Only privileged and certified apps may use Firefox Accounts",
"ERROR_INVALID_ASSERTION_AUDIENCE":
"Assertion audience may not differ from origin",
"ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT":
@@ -150,7 +148,12 @@ nsDOMIdentity.prototype = {
// broken client to be able to call watch() any more. It's broken.
return;
}
- this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:RP:Watch",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
request: function nsDOMIdentity_request(aOptions = {}) {
@@ -221,7 +224,12 @@ nsDOMIdentity.prototype = {
}
this._rpCalls++;
- this._identityInternal._mm.sendAsyncMessage("Identity:RP:Request", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:RP:Request",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
logout: function nsDOMIdentity_logout() {
@@ -241,7 +249,12 @@ nsDOMIdentity.prototype = {
return;
}
- this._identityInternal._mm.sendAsyncMessage("Identity:RP:Logout", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:RP:Logout",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
/*
@@ -324,8 +337,12 @@ nsDOMIdentity.prototype = {
}
this._beginProvisioningCallback = aCallback;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
- this.DOMIdentityMessage());
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:BeginProvisioning",
+ this.DOMIdentityMessage(),
+ null,
+ this._window.document.nodePrincipal
+ );
},
genKeyPair: function nsDOMIdentity_genKeyPair(aCallback) {
@@ -341,8 +358,12 @@ nsDOMIdentity.prototype = {
}
this._genKeyPairCallback = aCallback;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
- this.DOMIdentityMessage());
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:GenKeyPair",
+ this.DOMIdentityMessage(),
+ null,
+ this._window.document.nodePrincipal
+ );
},
registerCertificate: function nsDOMIdentity_registerCertificate(aCertificate) {
@@ -357,7 +378,12 @@ nsDOMIdentity.prototype = {
let message = this.DOMIdentityMessage();
message.cert = aCertificate;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:RegisterCertificate",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
raiseProvisioningFailure: function nsDOMIdentity_raiseProvisioningFailure(aReason) {
@@ -372,7 +398,12 @@ nsDOMIdentity.prototype = {
let message = this.DOMIdentityMessage();
message.reason = aReason;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:ProvisioningFailure",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
/**
@@ -392,8 +423,12 @@ nsDOMIdentity.prototype = {
}
this._beginAuthenticationCallback = aCallback;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
- this.DOMIdentityMessage());
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:BeginAuthentication",
+ this.DOMIdentityMessage(),
+ null,
+ this._window.document.nodePrincipal
+ );
},
completeAuthentication: function nsDOMIdentity_completeAuthentication() {
@@ -405,8 +440,12 @@ nsDOMIdentity.prototype = {
}
this._authenticationEnded = true;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
- this.DOMIdentityMessage());
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:CompleteAuthentication",
+ this.DOMIdentityMessage(),
+ null,
+ this._window.document.nodePrincipal
+ );
},
raiseAuthenticationFailure: function nsDOMIdentity_raiseAuthenticationFailure(aReason) {
@@ -419,7 +458,12 @@ nsDOMIdentity.prototype = {
let message = this.DOMIdentityMessage();
message.reason = aReason;
- this._identityInternal._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
+ this._identityInternal._mm.sendAsyncMessage(
+ "Identity:IDP:AuthenticationFailure",
+ message,
+ null,
+ this._window.document.nodePrincipal
+ );
},
// Private.
@@ -510,7 +554,8 @@ nsDOMIdentity.prototype = {
case "Identity:RP:Watch:OnCancel":
// Do we have a watcher?
if (!this._rpWatcher) {
- this._log("WARNING: Received OnCancel message, but there is no RP watcher");
+ this._log("WARNING: Received OnCancel message, but there is no RP " +
+ "watcher");
return;
}
@@ -520,7 +565,8 @@ nsDOMIdentity.prototype = {
break;
case "Identity:RP:Watch:OnError":
if (!this._rpWatcher) {
- this._log("WARNING: Received OnError message, but there is no RP watcher");
+ this._log("WARNING: Received OnError message, but there is no RP " +
+ "watcher");
return;
}
@@ -593,7 +639,6 @@ nsDOMIdentity.prototype = {
let message = {
errors: []
};
- let principal = Ci.nsIPrincipal;
objectCopy(aOptions, message);
@@ -603,19 +648,6 @@ nsDOMIdentity.prototype = {
// window origin
message.origin = this._origin;
- // On b2g, an app's status can be NOT_INSTALLED, INSTALLED, PRIVILEGED, or
- // CERTIFIED. Compare the appStatus value to the constants enumerated in
- // Ci.nsIPrincipal.APP_STATUS_*.
- message.appStatus = this._appStatus;
-
- // Currently, we only permit certified and privileged apps to use
- // Firefox Accounts.
- if (aOptions.wantIssuer == "firefox-accounts" &&
- this._appStatus !== principal.APP_STATUS_PRIVILEGED &&
- this._appStatus !== principal.APP_STATUS_CERTIFIED) {
- message.errors.push("ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS");
- }
-
// Normally the window origin will be the audience in assertions. On b2g,
// certified apps have the power to override this and declare any audience
// the want. Privileged apps can also declare a different audience, as
@@ -628,7 +660,7 @@ nsDOMIdentity.prototype = {
// and then post-message the results down to their app.
let _audience = message.origin;
if (message.audience && message.audience != message.origin) {
- if (this._appStatus === principal.APP_STATUS_CERTIFIED) {
+ if (this._appStatus === Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
_audience = message.audience;
this._log("Certified app setting assertion audience: " + _audience);
} else {
@@ -648,7 +680,9 @@ nsDOMIdentity.prototype = {
this._log("nsDOMIdentity uninit() " + this._id);
this._identityInternal._mm.sendAsyncMessage(
"Identity:RP:Unwatch",
- { id: this._id }
+ { id: this._id },
+ null,
+ this._window.document.nodePrincipal
);
}
diff --git a/dom/identity/tests/mochitest/file_declareAudience.html b/dom/identity/tests/mochitest/file_declareAudience.html
index 3313ca3ca83..e8514409d5b 100644
--- a/dom/identity/tests/mochitest/file_declareAudience.html
+++ b/dom/identity/tests/mochitest/file_declareAudience.html
@@ -22,31 +22,49 @@
window.realParent.postMessage(JSON.stringify(message), "*");
}
- function onready() {
- navigator.mozId.request();
- }
-
- function onlogin(backedAssertion) {
- postResults({success: true, backedAssertion: backedAssertion});
- }
-
- function onerror(error) {
- postResults({success: false, error: error});
- }
-
onmessage = function(event) {
- navigator.mozId.watch({
- wantIssuer: "firefox-accounts",
- audience: event.data.audience,
- onready: onready,
- onlogin: onlogin,
- onerror: onerror,
+ try {
+ navigator.mozId.watch({
+ wantIssuer: "firefox-accounts",
+ audience: event.data.audience,
+ onready: function() {
+ try {
+ navigator.mozId.request();
+ } catch(e) {
+ postResults({
+ success: false,
+ error: e,
+ appIndex: event.data.appIndex
+ });
+ }
+ },
+ onlogin: function(backedAssertion) {
+ postResults({
+ success: true,
+ backedAssertion: backedAssertion,
+ appIndex: event.data.appIndex
+ });
+ },
+ onerror: function(error) {
+ postResults({
+ success: false,
+ error: error,
+ appIndex: event.data.appIndex
+ });
+ },
- // onlogout will actually be called every time watch() is invoked,
- // because fxa will find no signed-in user and so trigger logout.
- // For this test, though, we don't care and just ignore logout.
- onlogout: function () {},
- });
+ // onlogout will actually be called every time watch() is invoked,
+ // because fxa will find no signed-in user and so trigger logout.
+ // For this test, though, we don't care and just ignore logout.
+ onlogout: function () {},
+ });
+ } catch (e) {
+ postResults({
+ success: false,
+ error: e,
+ appIndex: event.data.appIndex
+ });
+ }
};
diff --git a/dom/identity/tests/mochitest/file_syntheticEvents.html b/dom/identity/tests/mochitest/file_syntheticEvents.html
index 58cd005f5cc..74e105b7a70 100644
--- a/dom/identity/tests/mochitest/file_syntheticEvents.html
+++ b/dom/identity/tests/mochitest/file_syntheticEvents.html
@@ -23,24 +23,34 @@
window.realParent.postMessage(JSON.stringify(message), "*");
}
- function onready() {
- navigator.mozId.request();
- }
-
- function onlogin(backedAssertion) {
- postResults({success: true, backedAssertion: backedAssertion});
- }
-
- function onerror(error) {
- postResults({success: false, error: error});
- }
-
- onmessage = function(message) {
+ onmessage = function(event) {
navigator.mozId.watch({
- wantIssuer: message.data.wantIssuer,
- onready: onready,
- onerror: onerror,
- onlogin: onlogin,
+ wantIssuer: event.data.wantIssuer,
+ onready: function() {
+ try {
+ navigator.mozId.request();
+ } catch(e) {
+ postResults({
+ success: false,
+ error: e,
+ appIndex: event.data.appIndex
+ });
+ }
+ },
+ onlogin: function(backedAssertion) {
+ postResults({
+ success: true,
+ backedAssertion: backedAssertion,
+ appIndex: event.data.appIndex
+ });
+ },
+ onerror: function(error) {
+ postResults({
+ success: false,
+ error: error,
+ appIndex: event.data.appIndex
+ });
+ },
onlogout: function() {},
});
};
diff --git a/dom/identity/tests/mochitest/test_declareAudience.html b/dom/identity/tests/mochitest/test_declareAudience.html
index 4ef9daf5f4c..b80efda5b85 100644
--- a/dom/identity/tests/mochitest/test_declareAudience.html
+++ b/dom/identity/tests/mochitest/test_declareAudience.html
@@ -102,7 +102,7 @@ let apps = [
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
expected: {
success: false,
- underprivileged: false,
+ underprivileged: true,
},
},
{
@@ -114,6 +114,7 @@ let apps = [
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_declareAudience.html",
expected: {
success: true,
+ underprivileged: false,
},
},
{
@@ -129,9 +130,7 @@ let apps = [
},
];
-let appIndex = 0;
-let expectedErrors = 0;
-let receivedErrors = [];
+let eventsReceived = 0;
let testRunner = runTest();
// Successful tests will send exactly one message. But for error tests, we may
@@ -139,9 +138,24 @@ let testRunner = runTest();
// track of received errors; once they reach the expected count, we are done.
function receiveMessage(event) {
let result = JSON.parse(event.data);
- let app = apps[appIndex];
+ let app = apps[result.appIndex];
+ if (app.received) {
+ return;
+ }
+ apps[result.appIndex].received = true;
+
let expected = app.expected;
+ let expectedErrors = 0;
+ let receivedErrors = [];
+
+ if (expected.underprivileged) {
+ expectedErrors += 1;
+ }
+ if (expected.nopermission) {
+ expectedErrors += 1;
+ }
+
is(result.success, expected.success,
"Assertion request succeeds");
@@ -150,51 +164,41 @@ function receiveMessage(event) {
let components = extractAssertionComponents(result.backedAssertion);
is(components.payload.aud, app.wantAudience || app.origin,
"Got desired assertion audience");
-
} else {
receivedErrors.push(result.error);
}
- if (receivedErrors.length === expectedErrors) {
- if (expected.underprivileged) {
- ok(receivedErrors.indexOf("ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS") > -1,
- "Expect a complaint that this app cannot use FxA.");
- }
- if (!expected.success) {
- ok(receivedErrors.indexOf("ERROR_INVALID_ASSERTION_AUDIENCE") > -1,
- "Expect an error getting an assertion");
- }
+ ok(receivedErrors.length === expectedErrors,
+ "Received errors should be equal to expected errors");
- appIndex += 1;
-
- if (appIndex === apps.length) {
- window.removeEventListener("message", receiveMessage);
-
- FirefoxAccounts.fxAccountsManager = originalManager;
-
- SimpleTest.finish();
- return;
- }
-
- testRunner.next();
+ if (!expected.success && expected.underprivileged) {
+ ok(receivedErrors.indexOf("ERROR_INVALID_ASSERTION_AUDIENCE") > -1,
+ "Expect an error getting an assertion");
}
+
+ eventsReceived += 1;
+
+ if (eventsReceived === apps.length) {
+ window.removeEventListener("message", receiveMessage);
+
+ FirefoxAccounts.fxAccountsManager = originalManager;
+
+ SimpleTest.finish();
+
+ return;
+ }
+
+ testRunner.next();
}
window.addEventListener("message", receiveMessage, false, true);
function runTest() {
- for (let app of apps) {
- dump("** Testing " + app.title + "\n");
- // Set up state for message handler
- expectedErrors = 0;
- receivedErrors = [];
- if (!app.expected.success) {
- expectedErrors += 1;
- }
- if (app.expected.underprivileged) {
- expectedErrors += 1;
- }
+ let index;
+ for (let i = 0; i < apps.length; i++) {
+ let app = apps[i];
+ dump("\n\n** Testing " + app.title + "\n");
let iframe = document.createElement("iframe");
@@ -204,24 +208,35 @@ function runTest() {
document.getElementById("content").appendChild(iframe);
- iframe.addEventListener("load", function onLoad() {
- iframe.removeEventListener("load", onLoad);
+ index = i;
+ (function(_index) {
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad);
- let principal = iframe.contentDocument.nodePrincipal;
- is(principal.appStatus, app.appStatus,
- "Iframe's document.nodePrincipal has expected appStatus");
+ SpecialPowers.addPermission(
+ "firefox-accounts",
+ SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION,
+ iframe.contentDocument
+ );
- // Because the