Merge b2g-inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2014-07-11 15:59:34 -04:00
commit 08cc354053
45 changed files with 762 additions and 398 deletions

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="aebf432f334ec0b48eb358569b9dfbfbead48017"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="aebf432f334ec0b48eb358569b9dfbfbead48017"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "6f63b10d567e5a8fb51bbebe5e482294427cc05d",
"revision": "f705a3f96020c7d7aa5ec63bf3417db29e1ab2a2",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="aebf432f334ec0b48eb358569b9dfbfbead48017"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c47094a26c87ba71a3da4bae54febd0da21f3393"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="40cac290f0a3253d31242d7f50b1d2ddd2f47cda"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9ff55cd0aefea23e4c60e5844c155c6ebc2e632b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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"]
}
};

View File

@ -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;
}

View File

@ -37,6 +37,12 @@ public:
MOZ_ASSERT(mCellBroadcast);
mCellBroadcast = nullptr;
}
private:
~Listener()
{
MOZ_ASSERT(!mCellBroadcast);
}
};
NS_IMPL_ISUPPORTS(CellBroadcast::Listener, nsICellBroadcastListener)

View File

@ -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

View File

@ -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<nsRefPtr<IccListener>> mIccListeners;
};

View File

@ -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);
},

View File

@ -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
);
}

View File

@ -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
});
}
};
</script>

View File

@ -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() {},
});
};

View File

@ -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 <iframe mozapp> can't parent its way back to us, we
// provide this handle to our window so it can postMessage to us.
iframe.contentWindow.wrappedJSObject.realParent = window;
let principal = iframe.contentDocument.nodePrincipal;
is(principal.appStatus, app.appStatus,
"Iframe's document.nodePrincipal has expected appStatus");
// Test what we want to test, viz. whether or not the app can request
// an assertion with an audience the same as or different from its
// origin. The client will post back its success or failure in procuring
// an identity assertion from Firefox Accounts.
iframe.contentWindow.postMessage({audience: app.wantAudience}, "*");
}, false);
// Because the <iframe mozapp> can't parent its way back to us, we
// provide this handle to our window so it can postMessage to us.
iframe.contentWindow.wrappedJSObject.realParent = window;
// Test what we want to test, viz. whether or not the app can request
// an assertion with an audience the same as or different from its
// origin. The client will post back its success or failure in procuring
// an identity assertion from Firefox Accounts.
iframe.contentWindow.postMessage({
audience: app.wantAudience,
appIndex: _index
}, "*");
}, false);
})(index);
yield undefined;
}
}
@ -259,9 +274,8 @@ SpecialPowers.pushPrefEnv({"set":
["identity.fxaccounts.enabled", true],
["toolkit.identity.debug", true],
["dom.identity.syntheticEventsOk", true],
["security.apps.privileged.CSP.default", ""],
["security.apps.certified.CSP.default", ""],
["security.apps.privileged.CSP.default", "'inline-script';"],
["security.apps.certified.CSP.default", "'inline-script';"],
]},
function() {
testRunner.next();

View File

@ -85,6 +85,8 @@ SpecialPowers.pushPrefEnv({'set': [
['dom.identity.syntheticEventsOk', true], // so we can call request()
['toolkit.identity.debug', true], // verbose identity logging
['browser.dom.window.dump.enabled', true],
["security.apps.privileged.CSP.default", "'inline-script';"],
["security.apps.certified.CSP.default", "'inline-script';"],
]},
function () { testRunner.next(); }
);

View File

@ -80,19 +80,6 @@ let apps = [
],
},
},
{
title: "an installed app, which must may not use firefox accounts",
manifest: "https://example.com/manifest.webapp",
origin: "https://example.com",
uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html",
wantIssuer: "firefox-accounts",
expected: {
success: false,
errors: [
"ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS",
],
},
},
{
title: "a privileged app, which may use synthetic events",
manifest: "https://example.com/manifest_priv.webapp",
@ -115,15 +102,20 @@ let apps = [
},
];
let appIndex = 0;
let eventsReceived = 0;
let testRunner = runTest();
let receivedErrors = [];
function receiveMessage(event) {
dump("** Received response: " + event.data + "\n");
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 receivedErrors = [];
is(result.success, expected.success,
"Assertion request " + (expected.success ? "succeeds" : "fails"));
@ -132,40 +124,38 @@ function receiveMessage(event) {
receivedErrors.push(result.error);
}
if (receivedErrors.length === (expected.errors || []).length) {
receivedErrors.forEach((error) => {
ok(expected.errors.indexOf(error) > -1,
"Received " + error + ". " +
"Expected errors are: " + JSON.stringify(expected.errors));
});
ok(receivedErrors.length === (expected.errors || []).length,
"Received errors should be equal to expected errors");
appIndex += 1;
receivedErrors.forEach((error) => {
ok(expected.errors.indexOf(error) > -1,
"Received " + error + ". " +
"Expected errors are: " + JSON.stringify(expected.errors));
});
if (appIndex === apps.length) {
window.removeEventListener("message", receiveMessage);
eventsReceived += 1;
// Remove mock from DOMIdentity
DOMIdentity._mockIdentityService = null;
if (eventsReceived === apps.length) {
window.removeEventListener("message", receiveMessage);
// Restore original fxa manager
FirefoxAccounts.fxAccountsManager = originalManager;
FirefoxAccounts.fxAccountsManager = originalManager;
SimpleTest.finish();
return;
}
SimpleTest.finish();
testRunner.next();
return;
}
testRunner.next();
}
window.addEventListener("message", receiveMessage, false, true);
function runTest() {
for (let app of apps) {
let index;
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
dump("** Testing " + app.title + "\n");
receivedErrors = [];
let iframe = document.createElement("iframe");
iframe.setAttribute("mozapp", app.manifest);
@ -174,15 +164,26 @@ 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);
// Because the <iframe mozapp> can't parent its way back to us, we
// provide this handle to our window so it can postMessage to us.
iframe.contentWindow.wrappedJSObject.realParent = window;
iframe.contentWindow.postMessage({wantIssuer: app.wantIssuer}, "*");
}, false);
SpecialPowers.addPermission(
"firefox-accounts",
SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION,
iframe.contentDocument
);
// Because the <iframe mozapp> can't parent its way back to us, we
// provide this handle to our window so it can postMessage to us.
iframe.contentWindow.wrappedJSObject.realParent = window;
iframe.contentWindow.postMessage({
wantIssuer: app.wantIssuer,
appIndex: _index
}, "*");
}, false);
})(index);
yield undefined;
}
}
@ -193,9 +194,8 @@ SpecialPowers.pushPrefEnv({"set":
["dom.identity.enabled", true],
["identity.fxaccounts.enabled", true],
["toolkit.identity.debug", true],
["security.apps.privileged.CSP.default", ""],
["security.apps.certified.CSP.default", ""],
["security.apps.privileged.CSP.default", "'inline-script';"],
["security.apps.certified.CSP.default", "'inline-script';"],
]},
function() {
testRunner.next();

View File

@ -43,6 +43,9 @@ public:
return mInfo;
}
private:
~DOMMMIError() {}
private:
nsString mServiceCode;
Nullable<int16_t> mInfo;

View File

@ -78,6 +78,9 @@ public:
return mCdmaNetworkId;
}
private:
~MobileCellInfo() {}
private:
nsCOMPtr<nsPIDOMWindow> mWindow;
int32_t mGsmLocationAreaCode;

View File

@ -62,6 +62,12 @@ public:
MOZ_ASSERT(mMobileConnection);
mMobileConnection = nullptr;
}
private:
~Listener()
{
MOZ_ASSERT(!mMobileConnection);
}
};
NS_IMPL_ISUPPORTS(MobileConnection::Listener, nsIMobileConnectionListener)
@ -130,6 +136,11 @@ MobileConnection::Shutdown()
}
}
MobileConnection::~MobileConnection()
{
MOZ_ASSERT(!(mProvider || mListener || mVoice || mData));
}
JSObject*
MobileConnection::WrapObject(JSContext* aCx)
{

View File

@ -155,6 +155,9 @@ public:
IMPL_EVENT_HANDLER(radiostatechange)
IMPL_EVENT_HANDLER(clirmodechange)
private:
~MobileConnection();
private:
uint32_t mClientId;
nsCOMPtr<nsIMobileConnectionProvider> mProvider;

View File

@ -93,6 +93,9 @@ public:
return mCellInfo;
}
private:
~MobileConnectionInfo() {}
private:
bool mConnected;
bool mEmergencyCallsOnly;

View File

@ -61,6 +61,9 @@ public:
return Nullable<MobileNetworkState>();
}
private:
~MobileNetworkInfo() {}
private:
nsCOMPtr<nsPIDOMWindow> mWindow;
nsString mShortName;

View File

@ -382,7 +382,11 @@ NetworkStatsDB.prototype = {
debug("New stats: " + JSON.stringify(stats));
}
let request = aStore.index("network").openCursor(stats.network, "prev");
let lowerFilter = [stats.appId, stats.serviceType, stats.network, 0];
let upperFilter = [stats.appId, stats.serviceType, stats.network, ""];
let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
let request = aStore.openCursor(range, 'prev');
request.onsuccess = function onsuccess(event) {
let cursor = event.target.result;
if (!cursor) {
@ -401,16 +405,9 @@ NetworkStatsDB.prototype = {
return;
}
let value = cursor.value;
if (stats.appId != value.appId ||
(stats.appId == 0 && stats.serviceType != value.serviceType)) {
cursor.continue();
return;
}
// There are old samples
if (DEBUG) {
debug("Last value " + JSON.stringify(value));
debug("Last value " + JSON.stringify(cursor.value));
}
// Remove stats previous to now - VALUE_MAX_LENGTH

View File

@ -33,11 +33,23 @@ let emulator = (function() {
});
};
return {
run: run,
P2P_RE_INDEX_0 : 0,
P2P_RE_INDEX_1 : 1,
T1T_RE_INDEX : 2,
T2T_RE_INDEX : 3,
T3T_RE_INDEX : 4,
T4T_RE_INDEX : 5
};
}());
let NCI = (function() {
function activateRE(re) {
let deferred = Promise.defer();
let cmd = 'nfc nci rf_intf_activated_ntf ' + re;
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check activation of RE' + re);
deferred.resolve();
});
@ -49,7 +61,7 @@ let emulator = (function() {
let deferred = Promise.defer();
let cmd = 'nfc nci rf_intf_deactivate_ntf';
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check deactivate');
deferred.resolve();
});
@ -61,7 +73,7 @@ let emulator = (function() {
let deferred = Promise.defer();
let cmd = 'nfc nci rf_discover_ntf ' + re + ' ' + type;
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check discovery of RE' + re);
deferred.resolve();
});
@ -69,12 +81,23 @@ let emulator = (function() {
return deferred.promise;
};
function setTagData(re, flag, tnf, type, payload) {
return {
activateRE: activateRE,
deactivate: deactivate,
notifyDiscoverRE: notifyDiscoverRE,
LAST_NOTIFICATION: 0,
LIMIT_NOTIFICATION: 1,
MORE_NOTIFICATIONS: 2
};
}());
let TAG = (function() {
function setData(re, flag, tnf, type, payload) {
let deferred = Promise.defer();
let cmd = "nfc tag set " + re +
" [" + flag + "," + tnf + "," + type + "," + payload + ",]";
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), "OK", "set NDEF data of tag" + re);
deferred.resolve();
});
@ -82,24 +105,31 @@ let emulator = (function() {
return deferred.promise;
};
function clearTagData(re) {
function clearData(re) {
let deferred = Promise.defer();
let cmd = "nfc tag clear " + re;
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), "OK", "clear tag" + re);
deferred.resolve();
});
}
function snepPutNdef(dsap, ssap, flags, tnf, type, payload, id) {
return {
setData: setData,
clearData: clearData
};
}());
let SNEP = (function() {
function put(dsap, ssap, flags, tnf, type, payload, id) {
let deferred = Promise.defer();
let cmd = "nfc snep put " + dsap + " " + ssap + " [" + flags + "," +
tnf + "," +
type + "," +
payload + "," +
id + "]";
this.run(cmd, function(result) {
emulator.run(cmd, function(result) {
is(result.pop(), "OK", "send SNEP PUT");
deferred.resolve();
});
@ -108,13 +138,8 @@ let emulator = (function() {
};
return {
run: run,
activateRE: activateRE,
deactivate: deactivate,
notifyDiscoverRE: notifyDiscoverRE,
setTagData: setTagData,
clearTagData: clearTagData,
snepPutNdef: snepPutNdef
put: put,
SAP_NDEF: 4
};
}());
@ -152,18 +177,6 @@ function clearPendingMessages(type) {
});
}
function enableRE0() {
let deferred = Promise.defer();
let cmd = 'nfc nci rf_intf_activated_ntf 0';
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check activation of RE0');
deferred.resolve();
});
return deferred.promise;
}
function cleanUp() {
log('Cleaning up');
waitFor(function() {

View File

@ -4,7 +4,7 @@
'use strict';
/* globals log, is, ok, runTests, toggleNFC, runNextTest,
SpecialPowers, nfc, enableRE0 */
SpecialPowers, nfc */
const MARIONETTE_TIMEOUT = 30000;
const MARIONETTE_HEAD_JS = 'head.js';
@ -50,7 +50,7 @@ function testWithTargetNoSessionToken() {
function testWithSessionTokenWithTarget() {
log('testWithSessionTokenWithTarget');
toggleNFC(true)
.then(enableRE0)
.then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerOnpeerready)
.then(() => fireCheckP2PReg(MANIFEST_URL))
.then((result) => {
@ -69,7 +69,7 @@ function testWithSessionTokenWithTarget() {
function testWithSessionTokenNoTarget() {
log('testWithSessionTokenNoTarget');
toggleNFC(true)
.then(enableRE0)
.then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0))
.then(() => fireCheckP2PReg(MANIFEST_URL))
.then((result) => {
is(result, false,
@ -87,7 +87,7 @@ function testWithSessionTokenNoTarget() {
function testWithSessionTokenWrongTarget() {
log('testWithSessionTokenWrongTarget');
toggleNFC(true)
.then(enableRE0)
.then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerOnpeerready)
.then(() => fireCheckP2PReg(FAKE_MANIFEST_URL))
.then((result) => {

View File

@ -27,7 +27,7 @@ let sessionTokens = [];
function testNfcNotEnabledError() {
log('testNfcNotEnabledError');
toggleNFC(true)
.then(() => emulator.activateRE(0))
.then(() => emulator.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerAndFireOnpeerready)
.then(() => toggleNFC(false))
.then(() => sendNDEFExpectError(nfcPeers[0], 'NfcNotEnabledError'))
@ -45,10 +45,10 @@ function testNfcNotEnabledError() {
function testNfcBadSessionIdError() {
log('testNfcBadSessionIdError');
toggleNFC(true)
.then(() => emulator.activateRE(0))
.then(() => emulator.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerAndFireOnpeerready)
.then(() => emulator.deactivate())
.then(() => emulator.activateRE(0))
.then(() => emulator.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerAndFireOnpeerready)
// we have 2 peers in nfcPeers array, peer0 has old/invalid session token
.then(() => sendNDEFExpectError(nfcPeers[0], 'NfcBadSessionIdError'))
@ -65,7 +65,7 @@ function testNfcBadSessionIdError() {
function testNfcConnectError() {
log('testNfcConnectError');
toggleNFC(true)
.then(() => emulator.activateRE(0))
.then(() => emulator.activateRE(emulator.P2P_RE_INDEX_0))
.then(registerAndFireOnpeerready)
.then(() => connectToNFCTagExpectError(sessionTokens[0],
'NDEF',
@ -83,7 +83,7 @@ function testNfcConnectError() {
function testNoErrorInTechMsg() {
log('testNoErrorInTechMsg');
toggleNFC(true)
.then(() => emulator.activateRE(0))
.then(() => emulator.activateRE(emulator.P2P_RE_INDEX_0))
.then(setTechDiscoveredHandler)
.then(setAndFireTechLostHandler)
.then(() => toggleNFC(false))

View File

@ -4,11 +4,6 @@
MARIONETTE_TIMEOUT = 30000;
MARIONETTE_HEAD_JS = 'head.js';
// See nfc-nci.h.
const NCI_LAST_NOTIFICATION = 0;
const NCI_LIMIT_NOTIFICATION = 1;
const NCI_MORE_NOTIFICATIONS = 2;
function handleTechnologyDiscoveredRE0(msg) {
log('Received \'nfc-manager-tech-discovered\'');
is(msg.type, 'techDiscovered', 'check for correct message type');
@ -21,7 +16,7 @@ function testActivateRE0() {
window.navigator.mozSetMessageHandler(
'nfc-manager-tech-discovered', handleTechnologyDiscoveredRE0);
toggleNFC(true).then(() => emulator.activateRE(0));
toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
// Check NCI Spec 5.2, this will change NCI state from
@ -32,9 +27,9 @@ function testRfDiscover() {
'nfc-manager-tech-discovered', handleTechnologyDiscoveredRE0);
toggleNFC(true)
.then(() => emulator.notifyDiscoverRE(0, NCI_MORE_NOTIFICATIONS))
.then(() => emulator.notifyDiscoverRE(1, NCI_LAST_NOTIFICATION))
.then(() => emulator.activateRE(0));
.then(() => NCI.notifyDiscoverRE(emulator.P2P_RE_INDEX_0, NCI.MORE_NOTIFICATIONS))
.then(() => NCI.notifyDiscoverRE(emulator.P2P_RE_INDEX_1, NCI.LAST_NOTIFICATION))
.then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
let tests = [

View File

@ -11,11 +11,6 @@ let id = "";
let ndef = null;
// See nfc-nci.h.
const NCI_LAST_NOTIFICATION = 0;
const NCI_LIMIT_NOTIFICATION = 1;
const NCI_MORE_NOTIFICATIONS = 2;
function handleTechnologyDiscoveredRE0(msg) {
log("Received 'nfc-manager-tech-discovered'");
is(msg.type, "techDiscovered", "check for correct message type");
@ -38,9 +33,9 @@ function testReceiveNDEF() {
window.navigator.mozSetMessageHandler(
"nfc-manager-tech-discovered", handleTechnologyDiscoveredRE0);
toggleNFC(true)
.then(() => emulator.activateRE(0))
.then(() => emulator.snepPutNdef(4, 4, 0, tnf, btoa(type),
btoa(payload), btoa(id)));
.then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0))
.then(() => SNEP.put(SNEP.SAP_NDEF, SNEP.SAP_NDEF, 0, tnf, btoa(type),
btoa(payload), btoa(id)));
}
let tests = [

View File

@ -16,7 +16,7 @@ function handleTechnologyDiscoveredRE0(msg) {
is(msg.type, 'techDiscovered', 'check for correct message type');
is(msg.techList[0], 'P2P', 'check for correct tech type');
emulator.deactivate();
NCI.deactivate();
}
function testTechLost() {
@ -26,7 +26,7 @@ function testTechLost() {
window.navigator.mozSetMessageHandler(
'nfc-manager-tech-lost', handleTechnologyLost);
toggleNFC(true).then(() => emulator.activateRE(0));
toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
let tests = [

View File

@ -14,7 +14,7 @@ function peerReadyCb(evt) {
// reset callback.
nfc.onpeerready = null;
emulator.deactivate();
NCI.deactivate();
}
function peerLostCb() {
@ -71,14 +71,14 @@ function testPeerReady() {
window.navigator.mozSetMessageHandler(
"nfc-manager-tech-discovered", handleTechnologyDiscoveredRE0);
toggleNFC(true).then(() => emulator.activateRE(0));
toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
function testCheckP2PRegFailure() {
window.navigator.mozSetMessageHandler(
"nfc-manager-tech-discovered", handleTechnologyDiscoveredRE0ForP2PRegFailure);
toggleNFC(true).then(() => emulator.activateRE(0));
toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
function testCheckNfcPeerObjForInvalidToken() {

View File

@ -44,7 +44,7 @@ function testOnPeerReadyRE0() {
log("Running \'testOnPeerReadyRE0\'");
window.navigator.mozSetMessageHandler(
"nfc-manager-tech-discovered", handleTechnologyDiscoveredRE0);
toggleNFC(true).then(enableRE0);
toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
}
let tests = [

View File

@ -6,11 +6,6 @@ MARIONETTE_HEAD_JS = "head.js";
let url = "http://www.mozilla.org";
const T1T_RE_INDEX = 2;
const T2T_RE_INDEX = 3;
const T3T_RE_INDEX = 4;
const T4T_RE_INDEX = 5;
function testUrlTagDiscover(re) {
log("Running \'testUrlTagDiscover\'");
// TODO : Make flag value readable.
@ -36,8 +31,8 @@ function testUrlTagDiscover(re) {
});
toggleNFC(true)
.then(() => emulator.setTagData(re, flag, tnf, btoa(type), btoa(payload)))
.then(() => emulator.activateRE(re));
.then(() => TAG.setData(re, flag, tnf, btoa(type), btoa(payload)))
.then(() => NCI.activateRE(re));
}
function testEmptyTagDiscover(re) {
@ -56,40 +51,40 @@ function testEmptyTagDiscover(re) {
});
toggleNFC(true)
.then(() => emulator.clearTagData(re))
.then(() => emulator.activateRE(re));
.then(() => TAG.clearData(re))
.then(() => NCI.activateRE(re));
}
function testUrlT1TDiscover() {
testUrlTagDiscover(T1T_RE_INDEX);
testUrlTagDiscover(emulator.T1T_RE_INDEX);
}
function testUrlT2TDiscover() {
testUrlTagDiscover(T2T_RE_INDEX);
testUrlTagDiscover(emulator.T2T_RE_INDEX);
}
function testUrlT3TDiscover() {
testUrlTagDiscover(T3T_RE_INDEX);
testUrlTagDiscover(emulator.T3T_RE_INDEX);
}
function testUrlT4TDiscover() {
testUrlTagDiscover(T4T_RE_INDEX);
testUrlTagDiscover(emulator.T4T_RE_INDEX);
}
function testEmptyT1TDiscover() {
testEmptyTagDiscover(T1T_RE_INDEX);
testEmptyTagDiscover(emulator.T1T_RE_INDEX);
}
function testEmptyT2TDiscover() {
testEmptyTagDiscover(T2T_RE_INDEX);
testEmptyTagDiscover(emulator.T2T_RE_INDEX);
}
function testEmptyT3TDiscover() {
testEmptyTagDiscover(T3T_RE_INDEX);
testEmptyTagDiscover(emulator.T3T_RE_INDEX);
}
function testEmptyT4TDiscover() {
testEmptyTagDiscover(T4T_RE_INDEX);
testEmptyTagDiscover(emulator.T4T_RE_INDEX);
}
let tests = [

View File

@ -39,6 +39,12 @@ public:
MOZ_ASSERT(mVoicemail);
mVoicemail = nullptr;
}
private:
~Listener()
{
MOZ_ASSERT(!mVoicemail);
}
};
NS_IMPL_ISUPPORTS(Voicemail::Listener, nsIVoicemailListener)

View File

@ -60,6 +60,8 @@ XPCOMUtils.defineLazyGetter(this, 'logPII', function() {
}
});
this.FXACCOUNTS_PERMISSION = "firefox-accounts";
this.DATA_FORMAT_VERSION = 1;
this.DEFAULT_STORAGE_FILENAME = "signedInUser.json";
@ -141,6 +143,7 @@ this.ERROR_NO_TOKEN_SESSION = "NO_TOKEN_SESSION";
this.ERROR_NO_SILENT_REFRESH_AUTH = "NO_SILENT_REFRESH_AUTH";
this.ERROR_NOT_VALID_JSON_BODY = "NOT_VALID_JSON_BODY";
this.ERROR_OFFLINE = "OFFLINE";
this.ERROR_PERMISSION_DENIED = "PERMISSION_DENIED";
this.ERROR_REQUEST_BODY_TOO_LARGE = "REQUEST_BODY_TOO_LARGE";
this.ERROR_SERVER_ERROR = "SERVER_ERROR";
this.ERROR_TOO_MANY_CLIENT_REQUESTS = "TOO_MANY_CLIENT_REQUESTS";

View File

@ -21,6 +21,10 @@ Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
"@mozilla.org/permissionmanager;1",
"nsIPermissionManager");
this.FxAccountsManager = {
init: function() {
@ -175,7 +179,7 @@ this.FxAccountsManager = {
* FxAccountsClient.signCertificate()
* See the latter method for possible (error code, errno) pairs.
*/
_handleGetAssertionError: function(reason, aAudience) {
_handleGetAssertionError: function(reason, aAudience, aPrincipal) {
let errno = (reason ? reason.errno : NaN) || NaN;
// If the previously valid email/password pair is no longer valid ...
if (errno == ERRNO_INVALID_AUTH_TOKEN) {
@ -186,34 +190,42 @@ this.FxAccountsManager = {
if (exists) {
return this.getAccount().then(
(user) => {
return this._refreshAuthentication(aAudience, user.email, true);
}
);
// ... otherwise, the account was deleted, so ask for Sign In/Up
} else {
return this._localSignOut().then(
() => {
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience);
},
(reason) => { // reject primary problem, not signout failure
log.error("Signing out in response to server error threw: " + reason);
return this._error(reason);
return this._refreshAuthentication(aAudience, user.email,
aPrincipal,
true /* logoutOnFailure */);
}
);
}
}
);
// Otherwise, the account was deleted, so ask for Sign In/Up
return this._localSignOut().then(
() => {
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience,
aPrincipal);
},
(reason) => {
// reject primary problem, not signout failure
log.error("Signing out in response to server error threw: " +
reason);
return this._error(reason);
}
);
}
return Promise.reject(reason);
},
_getAssertion: function(aAudience) {
_getAssertion: function(aAudience, aPrincipal) {
return this._fxAccounts.getAssertion(aAudience).then(
(result) => {
if (aPrincipal) {
this._addPermission(aPrincipal);
}
return result;
},
(reason) => {
return this._handleGetAssertionError(reason, aAudience);
return this._handleGetAssertionError(reason, aAudience, aPrincipal);
}
);
},
@ -228,10 +240,11 @@ this.FxAccountsManager = {
* 2) The person typing can't prove knowledge of the password used
* to log in. Failure should do nothing.
*/
_refreshAuthentication: function(aAudience, aEmail, logoutOnFailure=false) {
_refreshAuthentication: function(aAudience, aEmail, aPrincipal,
logoutOnFailure=false) {
this._refreshing = true;
return this._uiRequest(UI_REQUEST_REFRESH_AUTH,
aAudience, aEmail).then(
aAudience, aPrincipal, aEmail).then(
(assertion) => {
this._refreshing = false;
return assertion;
@ -293,7 +306,7 @@ this.FxAccountsManager = {
);
},
_uiRequest: function(aRequest, aAudience, aParams) {
_uiRequest: function(aRequest, aAudience, aPrincipal, aParams) {
let ui = Cc["@mozilla.org/fxaccounts/fxaccounts-ui-glue;1"]
.createInstance(Ci.nsIFxAccountsUIGlue);
if (!ui[aRequest]) {
@ -309,7 +322,7 @@ this.FxAccountsManager = {
// Even if we get a successful result from the UI, the account will
// most likely be unverified, so we cannot get an assertion.
if (result && result.verified) {
return this._getAssertion(aAudience);
return this._getAssertion(aAudience, aPrincipal);
}
return this._error(ERROR_UNVERIFIED_ACCOUNT, {
@ -322,6 +335,17 @@ this.FxAccountsManager = {
);
},
_addPermission: function(aPrincipal) {
// This will fail from tests cause we are running them in the child
// process until we have chrome tests in b2g. Bug 797164.
try {
permissionManager.addFromPrincipal(aPrincipal, FXACCOUNTS_PERMISSION,
Ci.nsIPermissionManager.ALLOW_ACTION);
} catch (e) {
log.warn("Could not add permission " + e);
}
},
// -- API --
signIn: function(aEmail, aPassword) {
@ -469,22 +493,31 @@ this.FxAccountsManager = {
* trigger the sign in flow.
* else if we were asked to refresh and the grace period is up:
* trigger the refresh flow.
* else ask the core code for an assertion, which might itself
* trigger either the sign in or refresh flows (if our account
* changed on the server).
* else:
* request user permission to share an assertion if we don't have it
* already and ask the core code for an assertion, which might itself
* trigger either the sign in or refresh flows (if our account
* changed on the server).
*
* aOptions can include:
* refreshAuthentication - (bool) Force re-auth.
* silent - (bool) Prevent any UI interaction.
* I.e., try to get an automatic assertion.
*/
getAssertion: function(aAudience, aOptions) {
getAssertion: function(aAudience, aPrincipal, aOptions) {
if (!aAudience) {
return this._error(ERROR_INVALID_AUDIENCE);
}
if (Services.io.offline) {
return this._error(ERROR_OFFLINE);
}
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
let uri = Services.io.newURI(aPrincipal.origin, null, null);
let principal = secMan.getAppCodebasePrincipal(uri,
aPrincipal.appId, aPrincipal.isInBrowserElement);
return this.getAccount().then(
user => {
if (user) {
@ -506,21 +539,42 @@ this.FxAccountsManager = {
if (aOptions.silent) {
return this._error(ERROR_NO_SILENT_REFRESH_AUTH);
}
let secondsSinceAuth = (Date.now() / 1000) - this._activeSession.authAt;
let secondsSinceAuth = (Date.now() / 1000) -
this._activeSession.authAt;
if (secondsSinceAuth > gracePeriod) {
return this._refreshAuthentication(aAudience, user.email);
return this._refreshAuthentication(aAudience, user.email,
principal,
false /* logoutOnFailure */);
}
}
// Third case: we are all set *locally*. Probably we just return
// the assertion, but the attempt might lead to the server saying
// we are deleted or have a new password, which will trigger a flow.
return this._getAssertion(aAudience);
// Also we need to check if we have permission to get the assertion,
// otherwise we need to show the forceAuth UI to let the user know
// that the RP with no fxa permissions is trying to obtain an
// assertion. Once the user authenticates herself in the forceAuth UI
// the permission will be remembered by default.
let permission = permissionManager.testPermissionFromPrincipal(
principal,
FXACCOUNTS_PERMISSION
);
if (permission == Ci.nsIPermissionManager.PROMPT_ACTION &&
!this._refreshing) {
return this._refreshAuthentication(aAudience, user.email,
principal,
false /* logoutOnFailure */);
} else if (permission == Ci.nsIPermissionManager.DENY_ACTION &&
!this._refreshing) {
return this._error(ERROR_PERMISSION_DENIED);
}
return this._getAssertion(aAudience, principal);
}
log.debug("No signed in user");
if (aOptions && aOptions.silent) {
return Promise.resolve(null);
}
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience);
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience, principal);
}
);
}

View File

@ -293,6 +293,7 @@ this.MobileIdentityManager = {
},
getCertificate: function(aSessionToken, aPublicKey) {
log.debug("getCertificate");
if (this.certificates[aSessionToken] &&
this.certificates[aSessionToken].validUntil > this.client.hawk.now()) {
return Promise.resolve(this.certificates[aSessionToken].cert);
@ -308,6 +309,7 @@ this.MobileIdentityManager = {
aPublicKey)
.then(
(signedCert) => {
log.debug("Got signed certificate");
this.certificates[aSessionToken] = {
cert: signedCert.cert,
validUntil: validUntil
@ -357,6 +359,25 @@ this.MobileIdentityManager = {
this.doVerification();
},
/*********************************************************
* Result helpers
*********************************************************/
success: function(aPromiseId, aResult) {
let mm = this.messageManagers[aPromiseId];
mm.sendAsyncMessage("MobileId:GetAssertion:Return:OK", {
promiseId: aPromiseId,
result: aResult
});
},
error: function(aPromiseId, aError) {
let mm = this.messageManagers[aPromiseId];
mm.sendAsyncMessage("MobileId:GetAssertion:Return:KO", {
promiseId: aPromiseId,
error: aError
});
},
/*********************************************************
* Permissions helper
********************************************************/
@ -565,6 +586,7 @@ this.MobileIdentityManager = {
return this.ui.startFlow(aManifestURL, phoneInfoArray)
.then(
(result) => {
log.debug("startFlow result ${} ", result);
if (!result ||
(!result.phoneNumber && (result.serviceId === undefined))) {
return Promise.reject(ERROR_INTERNAL_INVALID_PROMPT_RESULT);
@ -576,7 +598,9 @@ this.MobileIdentityManager = {
// If the user selected one of the existing SIM cards we have to check
// that we either have the MSISDN for that SIM or we can do a silent
// verification that does not require us to have the MSISDN in advance.
if (result.serviceId !== undefined) {
// result.serviceId can be "0".
if (result.serviceId !== undefined &&
result.serviceId !== null) {
let icc = this.iccInfo[result.serviceId];
log.debug("icc ${}", icc);
if (!icc || !icc.msisdn && !icc.canDoSilentVerification) {
@ -774,9 +798,22 @@ this.MobileIdentityManager = {
let uri = Services.io.newURI(aPrincipal.origin, null, null);
let principal = securityManager.getAppCodebasePrincipal(
uri, aPrincipal.appid, aPrincipal.isInBrowserElement);
uri, aPrincipal.appId, aPrincipal.isInBrowserElement);
let manifestURL = appsService.getManifestURLByLocalId(aPrincipal.appId);
let permission = permissionManager.testPermissionFromPrincipal(
principal,
MOBILEID_PERM
);
if (permission == Ci.nsIPermissionManager.DENY_ACTION ||
permission == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
this.error(aPromiseId, ERROR_PERMISSION_DENIED);
return;
}
let _creds;
// First of all we look if we already have credentials for this origin.
// If we don't have credentials it means that it is the first time that
// the caller requested an assertion.
@ -790,9 +827,11 @@ this.MobileIdentityManager = {
return;
}
_creds = creds;
// Even if we already have credentials for this origin, the consumer
// of the API might want to force the identity selection dialog.
if (aOptions.forceSelection) {
if (aOptions.forceSelection || aOptions.refreshCredentials) {
return this.promptAndVerify(principal, manifestURL, creds)
.then(
(newCreds) => {
@ -855,15 +894,8 @@ this.MobileIdentityManager = {
// If we've just prompted the user in the previous step, the permission
// is already granted and stored so we just progress the credentials.
if (creds) {
let permission = permissionManager.testPermissionFromPrincipal(
principal,
MOBILEID_PERM
);
if (permission == Ci.nsIPermissionManager.ALLOW_ACTION) {
return creds;
} else if (permission == Ci.nsIPermissionManager.DENY_ACTION ||
permission == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
return Promise.reject(ERROR_PERMISSION_DENIED);
}
return this.promptAndVerify(principal, manifestURL, creds);
}
@ -901,25 +933,31 @@ this.MobileIdentityManager = {
this.ui.verified(decodedPayload.verifiedMSISDN);
let mm = this.messageManagers[aPromiseId];
mm.sendAsyncMessage("MobileId:GetAssertion:Return:OK", {
promiseId: aPromiseId,
result: assertion
});
this.success(aPromiseId, assertion);
}
)
.then(
null,
(error) => {
log.error("getMobileIdAssertion rejected with " + error);
log.error("getMobileIdAssertion rejected with ${}", error);
// If we got an invalid token error means that the credentials that
// we have are not valid anymore and so we need to refresh them. We
// do that removing the stored credentials and starting over. We also
// make sure that we do this only once.
if (error === ERROR_INVALID_AUTH_TOKEN &&
!aOptions.refreshCredentials) {
log.debug("Need to get new credentials");
aOptions.refreshCredentials = true;
_creds && this.credStore.delete(_creds.msisdn);
this.getMobileIdAssertion(aPrincipal, aPromiseId, aOptions);
return;
}
// Notify the error to the UI.
this.ui.error(error);
let mm = this.messageManagers[aPromiseId];
mm.sendAsyncMessage("MobileId:GetAssertion:Return:KO", {
promiseId: aPromiseId,
error: error
});
this.error(aPromiseId, error);
}
);
},

View File

@ -29,9 +29,10 @@ const GET_ASSERTION_RETURN_KO = "MobileId:GetAssertion:Return:KO";
// === Globals ===
const ORIGIN = "app://afakeorigin";
const APP_ID = 1;
const PRINCIPAL = {
origin: ORIGIN,
appId: "123"
appId: APP_ID
};
const PHONE_NUMBER = "+34666555444";
const ANOTHER_PHONE_NUMBER = "+44123123123";
@ -45,25 +46,25 @@ const CERTIFICATE = "eyJhbGciOiJEUzI1NiJ9.eyJsYXN0QXV0aEF0IjoxNDA0NDY5NzkyODc3LC
// === Helpers ===
function addPermission(aOrigin, aAction) {
function addPermission(aAction) {
let uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(aOrigin, null, null);
.newURI(ORIGIN, null, null);
let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(uri);
.getAppCodebasePrincipal(uri, APP_ID, false);
let pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
pm.addFromPrincipal(_principal, MOBILEID_PERM, aAction);
}
function removePermission(aOrigin) {
function removePermission() {
let uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(aOrigin, null, null);
.newURI(ORIGIN, null, null);
let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(uri);
.getAppCodebasePrincipal(uri, APP_ID, false);
let pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
pm.removeFromPrincipal(_principal, MOBILEID_PERM);
@ -194,8 +195,16 @@ MockCredStore.prototype = {
getByOrigin: function() {
this._spy("getByOrigin", arguments);
return Promise.resolve(this._options.getByOriginResult ||
this._getByOriginResult);
let result = this._getByOriginResult;
if (this._options.getByOriginResult) {
if (Array.isArray(this._options.getByOriginResult)) {
result = this._options.getByOriginResult.length ?
this._options.getByOriginResult.shift() : null;
} else {
result = this._options.getByOriginResult;
}
}
return Promise.resolve(result);
},
getByMsisdn: function() {
@ -223,6 +232,11 @@ MockCredStore.prototype = {
removeOrigin: function() {
this._spy("removeOrigin", arguments);
return Promise.resolve();
},
delete: function() {
this._spy("delete", arguments);
return Promise.resolve();
}
};
@ -239,15 +253,11 @@ MockClient.prototype = {
__proto__: Mock.prototype,
_discoverResult: {
verificationMethods: ["sms/momt", "sms/mt"],
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
},
"sms/momt": {
mtSender: "123",
moVerifier: "234"
}
}
},
@ -298,6 +308,12 @@ MockClient.prototype = {
sign: function() {
this._spy("sign", arguments);
if (this._options.signError) {
let error = Array.isArray(this._options.signError) ?
this._options.signError.shift() :
this._options.signError;
return Promise.reject(error);
}
return Promise.resolve(this._options.signResult || this._signResult);
}
};
@ -347,6 +363,7 @@ function cleanup() {
MobileIdentityManager.client = kMobileIdentityClient;
MobileIdentityManager.ui = null;
MobileIdentityManager.iccInfo = null;
removePermission(ORIGIN);
}
// Unregister mocks and restore original code.
@ -374,17 +391,7 @@ add_test(function() {
MobileIdentityManager.ui = ui;
let credStore = new MockCredStore();
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
}
});
let client = new MockClient();
MobileIdentityManager.client = client;
let promiseId = Date.now();
@ -442,6 +449,8 @@ add_test(function() {
}
};
addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
principal: PRINCIPAL,
@ -615,15 +624,6 @@ add_test(function() {
let credStore = new MockCredStore();
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
signResult: {
cert: "aInvalidCert"
},
@ -739,7 +739,7 @@ add_test(function() {
}
};
addPermission(ORIGIN, Ci.nsIPermissionManager.ALLOW_ACTION);
addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
@ -799,7 +799,7 @@ add_test(function() {
}
};
addPermission(ORIGIN, Ci.nsIPermissionManager.PROMPT_ACTION);
addPermission(Ci.nsIPermissionManager.PROMPT_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
@ -813,7 +813,7 @@ add_test(function() {
});
add_test(function() {
do_print("= Existing credentials - No Icc - Permission denied - OK result =");
do_print("= Existing credentials - No Icc - Permission denied - KO result =");
do_register_cleanup(cleanup);
@ -847,13 +847,11 @@ add_test(function() {
// Check spied calls.
// MockCredStore.
credStore._("getByOrigin").callsLength(1);
credStore._("getByOrigin").call(1).arg(1, ORIGIN);
credStore._("getByOrigin").callsLength(0);
// MockUI.
ui._("startFlow").callsLength(0);
ui._("error").callsLength(1);
ui._("error").call(1).arg(1, ERROR_PERMISSION_DENIED);
ui._("error").callsLength(0);
do_test_finished();
run_next_test();
@ -937,6 +935,8 @@ add_test(function() {
}
};
addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
principal: PRINCIPAL,
@ -977,15 +977,6 @@ add_test(function() {
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
verifyCodeResult: ANOTHER_PHONE_NUMBER,
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
registerResult: {
msisdnSessionToken: _sessionToken
}
@ -1161,15 +1152,6 @@ add_test(function() {
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
verifyCodeResult: ANOTHER_PHONE_NUMBER,
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
registerResult: {
msisdnSessionToken: _sessionToken
}
@ -1233,3 +1215,96 @@ add_test(function() {
}
});
});
add_test(function() {
do_print("= Existing credentials - No Icc - INVALID_AUTH_TOKEN - OK =");
do_register_cleanup(cleanup);
do_test_pending();
let _sessionToken = Date.now();
let existingCredentials = {
sessionToken: _sessionToken,
msisdn: PHONE_NUMBER,
origin: ORIGIN,
deviceIccIds: null
};
let ui = new MockUi({
startFlowResult: {
phoneNumber: PHONE_NUMBER
}
});
MobileIdentityManager.ui = ui;
let credStore = new MockCredStore({
getByOriginResult: [existingCredentials, null]
});
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
signError: [ERROR_INVALID_AUTH_TOKEN],
verifyCodeResult: PHONE_NUMBER,
registerResult: {
msisdnSessionToken: SESSION_TOKEN
}
});
MobileIdentityManager.client = client;
let promiseId = Date.now();
let mm = {
sendAsyncMessage: function(aMsg, aData) {
do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
// Check result.
do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
do_check_eq(typeof aData, "object");
do_check_eq(aData.promiseId, promiseId);
// Check spied calls.
// MockCredStore.
credStore._("getByOrigin").callsLength(2);
credStore._("getByOrigin").call(1).arg(1, ORIGIN);
credStore._("getByOrigin").call(2).arg(1, ORIGIN);
credStore._("getByMsisdn").callsLength(1);
credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
credStore._("add").callsLength(1);
credStore._("add").call(1).arg(1, undefined);
credStore._("add").call(1).arg(2, PHONE_NUMBER);
credStore._("add").call(1).arg(3, ORIGIN);
credStore._("add").call(1).arg(4, SESSION_TOKEN);
credStore._("add").call(1).arg(5, null);
credStore._("setDeviceIccIds").callsLength(0);
credStore._("delete").callsLength(1);
credStore._("delete").call(1).arg(1, PHONE_NUMBER);
// MockUI.
ui._("startFlow").callsLength(1);
ui._("verifyCodePrompt").callsLength(1);
ui._("verify").callsLength(1);
// MockClient.
client._("discover").callsLength(1);
client._("register").callsLength(1);
client._("smsMtVerify").callsLength(1);
client._("verifyCode").callsLength(1);
client._("sign").callsLength(1);
do_test_finished();
run_next_test();
}
};
addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
principal: PRINCIPAL,
target: mm,
json: {
promiseId: promiseId,
options: {}
}
});
});

View File

@ -102,11 +102,16 @@ FxAccountsService.prototype = {
}
},
cleanupRPRequest: function(aRp) {
aRp.pendingRequest = false;
this._rpFlows.set(aRp.id, aRp);
},
/**
* Register a listener for a given windowID as a result of a call to
* navigator.id.watch().
*
* @param aCaller
* @param aRPCaller
* (Object) an object that represents the caller document, and
* is expected to have properties:
* - id (unique, e.g. uuid)
@ -128,7 +133,9 @@ FxAccountsService.prototype = {
// Log the user in, if possible, and then call ready().
let runnable = {
run: () => {
this.fxAccountsManager.getAssertion(aRpCaller.audience, {silent:true}).then(
this.fxAccountsManager.getAssertion(aRpCaller.audience,
aRpCaller.principal,
{ silent:true }).then(
data => {
if (data) {
this.doLogin(aRpCaller.id, data);
@ -161,10 +168,10 @@ FxAccountsService.prototype = {
* navigator.id.request().
*
* @param aRPId
* (integer) the id of the doc object obtained in .watch()
* (integer) the id of the doc object obtained in .watch()
*
* @param aOptions
* (Object) options including privacyPolicy, termsOfService
* (Object) options including privacyPolicy, termsOfService
*/
request: function request(aRPId, aOptions) {
aOptions = aOptions || {};
@ -174,24 +181,48 @@ FxAccountsService.prototype = {
return;
}
// We check if we already have a pending request for this RP and in that
// case we just bail out. We don't want duplicated onlogin or oncancel
// events.
if (rp.pendingRequest) {
log.debug("request() already called");
return;
}
// Otherwise, we set the RP flow with the pending request flag.
rp.pendingRequest = true;
this._rpFlows.set(rp.id, rp);
let options = makeMessageObject(rp);
objectCopy(aOptions, options);
log.debug("get assertion for " + rp.audience);
this.fxAccountsManager.getAssertion(rp.audience, options).then(
this.fxAccountsManager.getAssertion(rp.audience, rp.principal, options)
.then(
data => {
log.debug("got assertion for " + rp.audience + ": " + data);
this.doLogin(aRPId, data);
},
error => {
log.error("get assertion failed: " + JSON.stringify(error));
log.debug("get assertion failed: " + JSON.stringify(error));
// Cancellation is passed through an error channel; here we reroute.
if (error.error && (error.error.details == "DIALOG_CLOSED_BY_USER")) {
if ((error.error && (error.error.details == "DIALOG_CLOSED_BY_USER")) ||
(error.details == "DIALOG_CLOSED_BY_USER")) {
return this.doCancel(aRPId);
}
this.doError(aRPId, error);
}
)
.then(
() => {
this.cleanupRPRequest(rp);
}
)
.catch(
() => {
this.cleanupRPRequest(rp);
}
);
},

View File

@ -982,6 +982,11 @@ nsAppShell::Init()
InitGonkMemoryPressureMonitoring();
if (XRE_GetProcessType() == GeckoProcessType_Default) {
printf("*****************************************************************\n");
printf("***\n");
printf("*** This is stdout. Most of the useful output will be in logcat.\n");
printf("***\n");
printf("*****************************************************************\n");
#ifdef MOZ_OMX_DECODER
android::MediaResourceManagerService::instantiate();
#endif