mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1146904: Add the FxAccountsWebChannel to drive Sync
* * * fix tests From 6bb486068a8b002f222f4658989968d86df9eff1 Mon Sep 17 00:00:00 2001 --- .../test/general/browser_fxa_web_channel.html | 2 +- .../test/general/browser_fxa_web_channel.js | 131 +++++++++++---------- services/fxaccounts/tests/xpcshell/test_profile.js | 26 ---- 3 files changed, 70 insertions(+), 89 deletions(-)
This commit is contained in:
parent
9a464ba7e7
commit
d76f64b841
@ -1808,6 +1808,9 @@ pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/
|
||||
// The remote content URL shown for signin in. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v1");
|
||||
|
||||
// The remote content URL where FxAccountsWebChannel messages originate.
|
||||
pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");
|
||||
|
||||
// The URL we take the user to when they opt to "manage" their Firefox Account.
|
||||
// Note that this will always need to be in the same TLD as the
|
||||
// "identity.fxaccounts.remote.signup.uri" pref.
|
||||
|
@ -88,6 +88,14 @@ let gFxAccounts = {
|
||||
// notified of fxa-migration:state-changed in response if necessary.
|
||||
Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
|
||||
|
||||
let contentUri = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.webchannel.uri");
|
||||
// The FxAccountsWebChannel listens for events and updates
|
||||
// the state machine accordingly.
|
||||
let fxAccountsWebChannel = new FxAccountsWebChannel({
|
||||
content_uri: contentUri,
|
||||
channel_id: this.FxAccountsCommon.WEBCHANNEL_ID
|
||||
});
|
||||
|
||||
this._initialized = true;
|
||||
|
||||
this.updateUI();
|
||||
@ -403,3 +411,6 @@ XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function () {
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(gFxAccounts, "fxaMigrator",
|
||||
"resource://services-sync/FxaMigrator.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsWebChannel",
|
||||
"resource://gre/modules/FxAccountsWebChannel.jsm");
|
||||
|
@ -13,7 +13,7 @@ support-files =
|
||||
browser_bug970746.xhtml
|
||||
browser_fxa_oauth.html
|
||||
browser_fxa_oauth_with_keys.html
|
||||
browser_fxa_profile_channel.html
|
||||
browser_fxa_web_channel.html
|
||||
browser_registerProtocolHandler_notification.html
|
||||
browser_ssl_error_reports_content.js
|
||||
browser_star_hsts.sjs
|
||||
@ -302,7 +302,7 @@ skip-if = e10s
|
||||
skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
|
||||
[browser_fxa_migrate.js]
|
||||
[browser_fxa_oauth.js]
|
||||
[browser_fxa_profile_channel.js]
|
||||
[browser_fxa_web_channel.js]
|
||||
[browser_gestureSupport.js]
|
||||
skip-if = e10s # Bug 863514 - no gesture support.
|
||||
[browser_getshortcutoruri.js]
|
||||
|
@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>fxa_profile_channel_test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "account_updates",
|
||||
message: {
|
||||
command: "profile:change",
|
||||
data: {
|
||||
uid: "abc123",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,90 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
|
||||
return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileChannel",
|
||||
"resource://gre/modules/FxAccountsProfileChannel.jsm");
|
||||
|
||||
const HTTP_PATH = "http://example.com";
|
||||
|
||||
let gTests = [
|
||||
{
|
||||
desc: "FxA Profile Channel - should receive message about account updates",
|
||||
run: function* () {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let tabOpened = false;
|
||||
let properUrl = "http://example.com/browser/browser/base/content/test/general/browser_fxa_profile_channel.html";
|
||||
|
||||
waitForTab(function (tab) {
|
||||
Assert.ok("Tab successfully opened");
|
||||
let match = gBrowser.currentURI.spec == properUrl;
|
||||
Assert.ok(match);
|
||||
|
||||
tabOpened = true;
|
||||
});
|
||||
|
||||
let client = new FxAccountsProfileChannel({
|
||||
content_uri: HTTP_PATH,
|
||||
});
|
||||
|
||||
makeObserver(FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
|
||||
Assert.ok(tabOpened);
|
||||
Assert.equal(data, "abc123");
|
||||
resolve();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab(properUrl);
|
||||
});
|
||||
}
|
||||
}
|
||||
]; // gTests
|
||||
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
let callback = function (aSubject, aTopic, aData) {
|
||||
if (aTopic == aObserveTopic) {
|
||||
removeMe();
|
||||
aObserveFunc(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
|
||||
function removeMe() {
|
||||
Services.obs.removeObserver(callback, aObserveTopic);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(callback, aObserveTopic, false);
|
||||
return removeMe;
|
||||
}
|
||||
|
||||
function waitForTab(aCallback) {
|
||||
let container = gBrowser.tabContainer;
|
||||
container.addEventListener("TabOpen", function tabOpener(event) {
|
||||
container.removeEventListener("TabOpen", tabOpener, false);
|
||||
gBrowser.addEventListener("load", function listener() {
|
||||
gBrowser.removeEventListener("load", listener, true);
|
||||
let tab = event.target;
|
||||
aCallback(tab);
|
||||
}, true);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function () {
|
||||
for (let test of gTests) {
|
||||
info("Running: " + test.desc);
|
||||
yield test.run();
|
||||
}
|
||||
}).then(finish, ex => {
|
||||
Assert.ok(false, "Unexpected Exception: " + ex);
|
||||
finish();
|
||||
});
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>fxa_web_channel_test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var webChannelId = "account_updates_test";
|
||||
|
||||
window.onload = function(){
|
||||
var testName = window.location.search.replace(/^\?/, "");
|
||||
|
||||
switch(testName) {
|
||||
case "profile_change":
|
||||
test_profile_change();
|
||||
break;
|
||||
case "login":
|
||||
test_login();
|
||||
break;
|
||||
case "can_link_account":
|
||||
test_can_link_account();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function test_profile_change() {
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: webChannelId,
|
||||
message: {
|
||||
command: "profile:change",
|
||||
data: {
|
||||
uid: "abc123",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function test_login() {
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: webChannelId,
|
||||
message: {
|
||||
command: "fxaccounts:login",
|
||||
data: {
|
||||
authAt: Date.now(),
|
||||
email: "testuser@testuser.com",
|
||||
keyFetchToken: 'key_fetch_token',
|
||||
sessionToken: 'session_token',
|
||||
uid: 'uid',
|
||||
unwrapBKey: 'unwrap_b_key',
|
||||
verified: true,
|
||||
},
|
||||
messageId: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function test_can_link_account() {
|
||||
window.addEventListener("WebChannelMessageToContent", function (e) {
|
||||
// echo any responses from the browser back to the tests on the
|
||||
// fxaccounts_webchannel_response_echo WebChannel. The tests are
|
||||
// listening for events and do the appropriate checks.
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: 'fxaccounts_webchannel_response_echo',
|
||||
message: e.detail.message,
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}, true);
|
||||
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: webChannelId,
|
||||
message: {
|
||||
command: "fxaccounts:can_link_account",
|
||||
data: {
|
||||
email: "testuser@testuser.com",
|
||||
},
|
||||
messageId: 2,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
153
browser/base/content/test/general/browser_fxa_web_channel.js
Normal file
153
browser/base/content/test/general/browser_fxa_web_channel.js
Normal file
@ -0,0 +1,153 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
|
||||
return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
|
||||
"resource://gre/modules/WebChannel.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsWebChannel",
|
||||
"resource://gre/modules/FxAccountsWebChannel.jsm");
|
||||
|
||||
const TEST_HTTP_PATH = "http://example.com";
|
||||
const TEST_BASE_URL = TEST_HTTP_PATH + "/browser/browser/base/content/test/general/browser_fxa_web_channel.html";
|
||||
const TEST_CHANNEL_ID = "account_updates_test";
|
||||
|
||||
let gTests = [
|
||||
{
|
||||
desc: "FxA Web Channel - should receive message about profile changes",
|
||||
run: function* () {
|
||||
let client = new FxAccountsWebChannel({
|
||||
content_uri: TEST_HTTP_PATH,
|
||||
channel_id: TEST_CHANNEL_ID,
|
||||
});
|
||||
let promiseObserver = new Promise((resolve, reject) => {
|
||||
makeObserver(FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
|
||||
Assert.equal(data, "abc123");
|
||||
client.tearDown();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: TEST_BASE_URL + "?profile_change"
|
||||
}, function* () {
|
||||
yield promiseObserver;
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "fxa web channel - login messages should notify the fxAccounts object",
|
||||
run: function* () {
|
||||
|
||||
let promiseLogin = new Promise((resolve, reject) => {
|
||||
let login = (accountData) => {
|
||||
Assert.equal(typeof accountData.authAt, 'number');
|
||||
Assert.equal(accountData.email, 'testuser@testuser.com');
|
||||
Assert.equal(accountData.keyFetchToken, 'key_fetch_token');
|
||||
Assert.equal(accountData.sessionToken, 'session_token');
|
||||
Assert.equal(accountData.uid, 'uid');
|
||||
Assert.equal(accountData.unwrapBKey, 'unwrap_b_key');
|
||||
Assert.equal(accountData.verified, true);
|
||||
|
||||
client.tearDown();
|
||||
resolve();
|
||||
};
|
||||
|
||||
let client = new FxAccountsWebChannel({
|
||||
content_uri: TEST_HTTP_PATH,
|
||||
channel_id: TEST_CHANNEL_ID,
|
||||
helpers: {
|
||||
login: login
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: TEST_BASE_URL + "?login"
|
||||
}, function* () {
|
||||
yield promiseLogin;
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "fxa web channel - can_link_account messages should respond",
|
||||
run: function* () {
|
||||
let properUrl = TEST_BASE_URL + "?can_link_account";
|
||||
|
||||
let promiseEcho = new Promise((resolve, reject) => {
|
||||
|
||||
let webChannelOrigin = Services.io.newURI(properUrl, null, null);
|
||||
// responses sent to content are echoed back over the
|
||||
// `fxaccounts_webchannel_response_echo` channel. Ensure the
|
||||
// fxaccounts:can_link_account message is responded to.
|
||||
let echoWebChannel = new WebChannel('fxaccounts_webchannel_response_echo', webChannelOrigin);
|
||||
echoWebChannel.listen((webChannelId, message, target) => {
|
||||
Assert.equal(message.command, 'fxaccounts:can_link_account');
|
||||
Assert.equal(message.messageId, 2);
|
||||
Assert.equal(message.data.ok, true);
|
||||
|
||||
client.tearDown();
|
||||
echoWebChannel.stopListening();
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
let client = new FxAccountsWebChannel({
|
||||
content_uri: TEST_HTTP_PATH,
|
||||
channel_id: TEST_CHANNEL_ID,
|
||||
helpers: {
|
||||
shouldAllowRelink(acctName) {
|
||||
return acctName === 'testuser@testuser.com';
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: properUrl
|
||||
}, function* () {
|
||||
yield promiseEcho;
|
||||
});
|
||||
}
|
||||
}
|
||||
]; // gTests
|
||||
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
let callback = function (aSubject, aTopic, aData) {
|
||||
if (aTopic == aObserveTopic) {
|
||||
removeMe();
|
||||
aObserveFunc(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
|
||||
function removeMe() {
|
||||
Services.obs.removeObserver(callback, aObserveTopic);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(callback, aObserveTopic, false);
|
||||
return removeMe;
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function () {
|
||||
for (let test of gTests) {
|
||||
info("Running: " + test.desc);
|
||||
yield test.run();
|
||||
}
|
||||
}).then(finish, ex => {
|
||||
Assert.ok(false, "Unexpected Exception: " + ex);
|
||||
finish();
|
||||
});
|
||||
}
|
@ -1406,9 +1406,9 @@ FxAccountsInternal.prototype = {
|
||||
*
|
||||
* @param options
|
||||
* {
|
||||
* contentUrl: (string) Used by the FxAccountsProfileChannel.
|
||||
* contentUrl: (string) Used by the FxAccountsWebChannel.
|
||||
* Defaults to pref identity.fxaccounts.settings.uri
|
||||
* profileServerUrl: (string) Used by the FxAccountsProfileChannel.
|
||||
* profileServerUrl: (string) Used by the FxAccountsWebChannel.
|
||||
* Defaults to pref identity.fxaccounts.remote.profile.uri
|
||||
* }
|
||||
*
|
||||
|
@ -100,8 +100,8 @@ exports.UI_REQUEST_REFRESH_AUTH = "refreshAuthentication";
|
||||
// The OAuth client ID for Firefox Desktop
|
||||
exports.FX_OAUTH_CLIENT_ID = "5882386c6d801776";
|
||||
|
||||
// Profile WebChannel ID
|
||||
exports.PROFILE_WEBCHANNEL_ID = "account_updates";
|
||||
// Firefox Accounts WebChannel ID
|
||||
exports.WEBCHANNEL_ID = "account_updates";
|
||||
|
||||
// Server errno.
|
||||
// From https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format
|
||||
|
@ -24,11 +24,6 @@ Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileClient",
|
||||
"resource://gre/modules/FxAccountsProfileClient.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileChannel",
|
||||
"resource://gre/modules/FxAccountsProfileChannel.jsm");
|
||||
|
||||
let fxAccountProfileChannel = null;
|
||||
|
||||
// Based off of deepEqual from Assert.jsm
|
||||
function deepEqual(actual, expected) {
|
||||
if (actual === expected) {
|
||||
@ -131,25 +126,10 @@ this.FxAccountsProfile.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
// Initialize a profile channel to listen for account changes.
|
||||
_listenForProfileChanges: function () {
|
||||
if (! fxAccountProfileChannel) {
|
||||
let contentUri = Services.urlFormatter.formatURLPref("identity.fxaccounts.settings.uri");
|
||||
|
||||
fxAccountProfileChannel = new FxAccountsProfileChannel({
|
||||
content_uri: contentUri
|
||||
});
|
||||
}
|
||||
|
||||
return fxAccountProfileChannel;
|
||||
},
|
||||
|
||||
// Returns cached data right away if available, then fetches the latest profile
|
||||
// data in the background. After data is fetched a notification will be sent
|
||||
// out if the profile has changed.
|
||||
getProfile: function () {
|
||||
this._listenForProfileChanges();
|
||||
|
||||
return this._getCachedProfile()
|
||||
.then(cachedProfile => {
|
||||
if (cachedProfile) {
|
||||
|
@ -1,118 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Firefox Accounts Profile update helper.
|
||||
* Uses the WebChannel component to receive messages about account changes.
|
||||
*/
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["FxAccountsProfileChannel"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
|
||||
"resource://gre/modules/WebChannel.jsm");
|
||||
|
||||
const PROFILE_CHANGE_COMMAND = "profile:change";
|
||||
|
||||
/**
|
||||
* Create a new FxAccountsProfileChannel to listen to profile updates
|
||||
*
|
||||
* @param {Object} options Options
|
||||
* @param {Object} options.parameters
|
||||
* @param {String} options.parameters.content_uri
|
||||
* The FxA Content server uri
|
||||
* @constructor
|
||||
*/
|
||||
this.FxAccountsProfileChannel = function(options) {
|
||||
if (!options) {
|
||||
throw new Error("Missing configuration options");
|
||||
}
|
||||
if (!options["content_uri"]) {
|
||||
throw new Error("Missing 'content_uri' option");
|
||||
}
|
||||
this.parameters = options;
|
||||
|
||||
this._setupChannel();
|
||||
};
|
||||
|
||||
this.FxAccountsProfileChannel.prototype = {
|
||||
/**
|
||||
* Configuration object
|
||||
*/
|
||||
parameters: null,
|
||||
/**
|
||||
* WebChannel that is used to communicate with content page
|
||||
*/
|
||||
_channel: null,
|
||||
/**
|
||||
* WebChannel origin, used to validate origin of messages
|
||||
*/
|
||||
_webChannelOrigin: null,
|
||||
|
||||
/**
|
||||
* Release all resources that are in use.
|
||||
*/
|
||||
tearDown: function() {
|
||||
this._channel.stopListening();
|
||||
this._channel = null;
|
||||
this._channelCallback = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Configures and registers a new WebChannel
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupChannel: function() {
|
||||
// if this.parameters.content_uri is present but not a valid URI, then this will throw an error.
|
||||
try {
|
||||
this._webChannelOrigin = Services.io.newURI(this.parameters.content_uri, null, null);
|
||||
this._registerChannel();
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new channel with the WebChannelBroker, setup a callback listener
|
||||
* @private
|
||||
*/
|
||||
_registerChannel: function() {
|
||||
/**
|
||||
* Processes messages that are called back from the FxAccountsChannel
|
||||
*
|
||||
* @param webChannelId {String}
|
||||
* Command webChannelId
|
||||
* @param message {Object}
|
||||
* Command message
|
||||
* @param target {EventTarget}
|
||||
* Channel message event target
|
||||
* @private
|
||||
*/
|
||||
let listener = (webChannelId, message, target) => {
|
||||
if (message) {
|
||||
let command = message.command;
|
||||
let data = message.data;
|
||||
switch (command) {
|
||||
case PROFILE_CHANGE_COMMAND:
|
||||
Services.obs.notifyObservers(null, ON_PROFILE_CHANGE_NOTIFICATION, data.uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._channelCallback = listener;
|
||||
this._channel = new WebChannel(PROFILE_WEBCHANNEL_ID, this._webChannelOrigin);
|
||||
this._channel.listen(this._channelCallback);
|
||||
log.debug("Channel registered: " + PROFILE_WEBCHANNEL_ID + " with origin " + this._webChannelOrigin.prePath);
|
||||
}
|
||||
|
||||
};
|
313
services/fxaccounts/FxAccountsWebChannel.jsm
Normal file
313
services/fxaccounts/FxAccountsWebChannel.jsm
Normal file
@ -0,0 +1,313 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Firefox Accounts Web Channel.
|
||||
*
|
||||
* Uses the WebChannel component to receive messages
|
||||
* about account state changes.
|
||||
*/
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["FxAccountsWebChannel"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
|
||||
"resource://gre/modules/WebChannel.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
|
||||
"resource://gre/modules/FxAccounts.jsm");
|
||||
|
||||
const COMMAND_PROFILE_CHANGE = "profile:change";
|
||||
const COMMAND_CAN_LINK_ACCOUNT = "fxaccounts:can_link_account";
|
||||
const COMMAND_LOGIN = "fxaccounts:login";
|
||||
|
||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||
const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync-setup.ui.showCustomizationDialog";
|
||||
|
||||
/**
|
||||
* Create a new FxAccountsWebChannel to listen for account updates
|
||||
*
|
||||
* @param {Object} options Options
|
||||
* @param {Object} options
|
||||
* @param {String} options.content_uri
|
||||
* The FxA Content server uri
|
||||
* @param {String} options.channel_id
|
||||
* The ID of the WebChannel
|
||||
* @param {String} options.helpers
|
||||
* Helpers functions. Should only be passed in for testing.
|
||||
* @constructor
|
||||
*/
|
||||
this.FxAccountsWebChannel = function(options) {
|
||||
if (!options) {
|
||||
throw new Error("Missing configuration options");
|
||||
}
|
||||
if (!options["content_uri"]) {
|
||||
throw new Error("Missing 'content_uri' option");
|
||||
}
|
||||
this._contentUri = options.content_uri;
|
||||
|
||||
if (!options["channel_id"]) {
|
||||
throw new Error("Missing 'channel_id' option");
|
||||
}
|
||||
this._webChannelId = options.channel_id;
|
||||
|
||||
// options.helpers is only specified by tests.
|
||||
this._helpers = options.helpers || new FxAccountsWebChannelHelpers(options);
|
||||
|
||||
this._setupChannel();
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannel.prototype = {
|
||||
/**
|
||||
* WebChannel that is used to communicate with content page
|
||||
*/
|
||||
_channel: null,
|
||||
|
||||
/**
|
||||
* Helpers interface that does the heavy lifting.
|
||||
*/
|
||||
_helpers: null,
|
||||
|
||||
/**
|
||||
* WebChannel ID.
|
||||
*/
|
||||
_webChannelId: null,
|
||||
/**
|
||||
* WebChannel origin, used to validate origin of messages
|
||||
*/
|
||||
_webChannelOrigin: null,
|
||||
|
||||
/**
|
||||
* Release all resources that are in use.
|
||||
*/
|
||||
tearDown() {
|
||||
this._channel.stopListening();
|
||||
this._channel = null;
|
||||
this._channelCallback = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Configures and registers a new WebChannel
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupChannel() {
|
||||
// if this.contentUri is present but not a valid URI, then this will throw an error.
|
||||
try {
|
||||
this._webChannelOrigin = Services.io.newURI(this._contentUri, null, null);
|
||||
this._registerChannel();
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new channel with the WebChannelBroker, setup a callback listener
|
||||
* @private
|
||||
*/
|
||||
_registerChannel() {
|
||||
/**
|
||||
* Processes messages that are called back from the FxAccountsChannel
|
||||
*
|
||||
* @param webChannelId {String}
|
||||
* Command webChannelId
|
||||
* @param message {Object}
|
||||
* Command message
|
||||
* @param sendingContext {Object}
|
||||
* Message sending context.
|
||||
* @param sendingContext.browser {browser}
|
||||
* The <browser> object that captured the
|
||||
* WebChannelMessageToChrome.
|
||||
* @param sendingContext.eventTarget {EventTarget}
|
||||
* The <EventTarget> where the message was sent.
|
||||
* @param sendingContext.principal {Principal}
|
||||
* The <Principal> of the EventTarget where the message was sent.
|
||||
* @private
|
||||
*
|
||||
*/
|
||||
let listener = (webChannelId, message, sendingContext) => {
|
||||
if (message) {
|
||||
log.debug("FxAccountsWebChannel message received", message);
|
||||
let command = message.command;
|
||||
let data = message.data;
|
||||
|
||||
switch (command) {
|
||||
case COMMAND_PROFILE_CHANGE:
|
||||
Services.obs.notifyObservers(null, ON_PROFILE_CHANGE_NOTIFICATION, data.uid);
|
||||
break;
|
||||
case COMMAND_LOGIN:
|
||||
this._helpers.login(data);
|
||||
break;
|
||||
case COMMAND_CAN_LINK_ACCOUNT:
|
||||
let canLinkAccount = this._helpers.shouldAllowRelink(data.email);
|
||||
|
||||
let response = {
|
||||
command: command,
|
||||
messageId: message.messageId,
|
||||
data: { ok: canLinkAccount }
|
||||
};
|
||||
|
||||
log.debug("FxAccountsWebChannel response", response);
|
||||
this._channel.send(response, sendingContext);
|
||||
break;
|
||||
default:
|
||||
log.warn("Unrecognized FxAccountsWebChannel command", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._channelCallback = listener;
|
||||
this._channel = new WebChannel(this._webChannelId, this._webChannelOrigin);
|
||||
this._channel.listen(listener);
|
||||
log.debug("FxAccountsWebChannel registered: " + this._webChannelId + " with origin " + this._webChannelOrigin.prePath);
|
||||
}
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannelHelpers = function(options) {
|
||||
options = options || {};
|
||||
|
||||
this._fxAccounts = options.fxAccounts || fxAccounts;
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannelHelpers.prototype = {
|
||||
// If the last fxa account used for sync isn't this account, we display
|
||||
// a modal dialog checking they really really want to do this...
|
||||
// (This is sync-specific, so ideally would be in sync's identity module,
|
||||
// but it's a little more seamless to do here, and sync is currently the
|
||||
// only fxa consumer, so...
|
||||
shouldAllowRelink(acctName) {
|
||||
return !this._needRelinkWarning(acctName) ||
|
||||
this._promptForRelink(acctName);
|
||||
},
|
||||
|
||||
/**
|
||||
* New users are asked in the content server whether they want to
|
||||
* customize which data should be synced. The user is only shown
|
||||
* the dialog listing the possible data types upon verification.
|
||||
*
|
||||
* Save a bit into prefs that is read on verification to see whether
|
||||
* to show the list of data types that can be saved.
|
||||
*/
|
||||
setShowCustomizeSyncPref(showCustomizeSyncPref) {
|
||||
Services.prefs.setBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION, showCustomizeSyncPref);
|
||||
},
|
||||
|
||||
getShowCustomizeSyncPref(showCustomizeSyncPref) {
|
||||
return Services.prefs.getBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION);
|
||||
},
|
||||
|
||||
/**
|
||||
* stores sync login info it in the fxaccounts service
|
||||
*
|
||||
* @param accountData the user's account data and credentials
|
||||
*/
|
||||
login(accountData) {
|
||||
if (accountData.customizeSync) {
|
||||
this.setShowCustomizeSyncPref(true);
|
||||
delete accountData.customizeSync;
|
||||
}
|
||||
|
||||
// the user has already been shown the "can link account"
|
||||
// screen. No need to keep this data around.
|
||||
delete accountData.verifiedCanLinkAccount;
|
||||
|
||||
// Remember who it was so we can log out next time.
|
||||
this.setPreviousAccountNameHashPref(accountData.email);
|
||||
|
||||
// A sync-specific hack - we want to ensure sync has been initialized
|
||||
// before we set the signed-in user.
|
||||
let xps = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
return xps.whenLoaded().then(() => {
|
||||
return this._fxAccounts.setSignedInUser(accountData);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the hash of account name of the previously signed in account
|
||||
*/
|
||||
getPreviousAccountNameHashPref() {
|
||||
try {
|
||||
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given an account name, set the hash of the previously signed in account
|
||||
*
|
||||
* @param acctName the account name of the user's account.
|
||||
*/
|
||||
setPreviousAccountNameHashPref(acctName) {
|
||||
let string = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
string.data = this.sha256(acctName);
|
||||
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a string, returns the SHA265 hash in base64
|
||||
*/
|
||||
sha256(str) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
// Data is an array of bytes.
|
||||
let data = converter.convertToByteArray(str, {});
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.SHA256);
|
||||
hasher.update(data, data.length);
|
||||
|
||||
return hasher.finish(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* If a user signs in using a different account, the data from the
|
||||
* previous account and the new account will be merged. Ask the user
|
||||
* if they want to continue.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_needRelinkWarning(acctName) {
|
||||
let prevAcctHash = this.getPreviousAccountNameHashPref();
|
||||
return prevAcctHash && prevAcctHash != this.sha256(acctName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the user a warning dialog that the data from the previous account
|
||||
* and the new account will be merged.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_promptForRelink(acctName) {
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
|
||||
let continueLabel = sb.GetStringFromName("continue.label");
|
||||
let title = sb.GetStringFromName("relinkVerify.title");
|
||||
let description = sb.formatStringFromName("relinkVerify.description",
|
||||
[acctName], 1);
|
||||
let body = sb.GetStringFromName("relinkVerify.heading") +
|
||||
"\n\n" + description;
|
||||
let ps = Services.prompt;
|
||||
let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
|
||||
(ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
|
||||
ps.BUTTON_POS_1_DEFAULT;
|
||||
|
||||
// If running in context of the browser chrome, window does not exist.
|
||||
var targetWindow = typeof window === 'undefined' ? null : window;
|
||||
let pressed = Services.prompt.confirmEx(targetWindow, title, body, buttonFlags,
|
||||
continueLabel, null, null, null,
|
||||
{});
|
||||
return pressed === 0; // 0 is the "continue" button
|
||||
}
|
||||
};
|
@ -17,8 +17,8 @@ EXTRA_JS_MODULES += [
|
||||
'FxAccountsOAuthClient.jsm',
|
||||
'FxAccountsOAuthGrantClient.jsm',
|
||||
'FxAccountsProfile.jsm',
|
||||
'FxAccountsProfileChannel.jsm',
|
||||
'FxAccountsProfileClient.jsm',
|
||||
'FxAccountsWebChannel.jsm',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
|
@ -154,20 +154,6 @@ add_test(function fetchAndCacheProfile_ok() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
add_test(function profile_channel() {
|
||||
let profile = new FxAccountsProfile(mockAccountData(), PROFILE_CLIENT_OPTIONS);
|
||||
|
||||
let channel = profile._listenForProfileChanges();
|
||||
do_check_true(!!channel);
|
||||
|
||||
let channel2 = profile._listenForProfileChanges();
|
||||
|
||||
do_check_eq(channel, channel2);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function tearDown_ok() {
|
||||
let profile = new FxAccountsProfile(mockAccountData(), PROFILE_CLIENT_OPTIONS);
|
||||
|
||||
@ -185,7 +171,6 @@ add_test(function getProfile_ok() {
|
||||
let cachedUrl = "myurl";
|
||||
let accountData = mockAccountData();
|
||||
let didFetch = false;
|
||||
let didListen = false;
|
||||
|
||||
let profile = new FxAccountsProfile(accountData, PROFILE_CLIENT_OPTIONS);
|
||||
profile._getCachedProfile = function () {
|
||||
@ -195,15 +180,11 @@ add_test(function getProfile_ok() {
|
||||
profile._fetchAndCacheProfile = function () {
|
||||
didFetch = true;
|
||||
};
|
||||
profile._listenForProfileChanges = function () {
|
||||
didListen = true;
|
||||
};
|
||||
|
||||
return profile.getProfile()
|
||||
.then(result => {
|
||||
do_check_eq(result.avatar, cachedUrl);
|
||||
do_check_true(didFetch);
|
||||
do_check_true(didListen);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
@ -211,7 +192,6 @@ add_test(function getProfile_ok() {
|
||||
add_test(function getProfile_no_cache() {
|
||||
let fetchedUrl = "newUrl";
|
||||
let accountData = mockAccountData();
|
||||
let didListen = false;
|
||||
|
||||
let profile = new FxAccountsProfile(accountData, PROFILE_CLIENT_OPTIONS);
|
||||
profile._getCachedProfile = function () {
|
||||
@ -221,22 +201,16 @@ add_test(function getProfile_no_cache() {
|
||||
profile._fetchAndCacheProfile = function () {
|
||||
return Promise.resolve({ avatar: fetchedUrl });
|
||||
};
|
||||
profile._listenForProfileChanges = function () {
|
||||
didListen = true;
|
||||
};
|
||||
|
||||
return profile.getProfile()
|
||||
.then(result => {
|
||||
do_check_eq(result.avatar, fetchedUrl);
|
||||
do_check_true(didListen);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function getProfile_has_cached_fetch_deleted() {
|
||||
let cachedUrl = "myurl";
|
||||
let didFetch = false;
|
||||
let didListen = false;
|
||||
|
||||
let client = mockClient();
|
||||
client.fetchProfile = function () {
|
||||
|
@ -1,75 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
Cu.import("resource://gre/modules/FxAccountsProfileChannel.jsm");
|
||||
|
||||
const URL_STRING = "https://example.com";
|
||||
|
||||
add_test(function () {
|
||||
validationHelper(undefined,
|
||||
"Error: Missing configuration options");
|
||||
|
||||
validationHelper({},
|
||||
"Error: Missing 'content_uri' option");
|
||||
|
||||
validationHelper({ content_uri: 'bad uri' },
|
||||
/NS_ERROR_MALFORMED_URI/);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function () {
|
||||
var mockMessage = {
|
||||
command: "profile:change",
|
||||
data: { uid: "foo" }
|
||||
};
|
||||
|
||||
makeObserver(ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
|
||||
do_check_eq(data, "foo");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
var channel = new FxAccountsProfileChannel({
|
||||
content_uri: URL_STRING
|
||||
});
|
||||
|
||||
channel._channelCallback(PROFILE_WEBCHANNEL_ID, mockMessage);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
let callback = function (aSubject, aTopic, aData) {
|
||||
log.debug("observed " + aTopic + " " + aData);
|
||||
if (aTopic == aObserveTopic) {
|
||||
removeMe();
|
||||
aObserveFunc(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
|
||||
function removeMe() {
|
||||
log.debug("removing observer for " + aObserveTopic);
|
||||
Services.obs.removeObserver(callback, aObserveTopic);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(callback, aObserveTopic, false);
|
||||
return removeMe;
|
||||
}
|
||||
|
||||
function validationHelper(params, expected) {
|
||||
try {
|
||||
new FxAccountsProfileChannel(params);
|
||||
} catch (e) {
|
||||
if (typeof expected === 'string') {
|
||||
return do_check_eq(e.toString(), expected);
|
||||
} else {
|
||||
return do_check_true(e.toString().match(expected));
|
||||
}
|
||||
}
|
||||
throw new Error("Validation helper error");
|
||||
}
|
236
services/fxaccounts/tests/xpcshell/test_web_channel.js
Normal file
236
services/fxaccounts/tests/xpcshell/test_web_channel.js
Normal file
@ -0,0 +1,236 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
const { FxAccountsWebChannel, FxAccountsWebChannelHelpers } =
|
||||
Cu.import("resource://gre/modules/FxAccountsWebChannel.jsm");
|
||||
|
||||
const URL_STRING = "https://example.com";
|
||||
|
||||
const mockSendingContext = {
|
||||
browser: {},
|
||||
principal: {},
|
||||
eventTarget: {}
|
||||
};
|
||||
|
||||
add_test(function () {
|
||||
validationHelper(undefined,
|
||||
"Error: Missing configuration options");
|
||||
|
||||
validationHelper({
|
||||
channel_id: WEBCHANNEL_ID
|
||||
},
|
||||
"Error: Missing 'content_uri' option");
|
||||
|
||||
validationHelper({
|
||||
content_uri: 'bad uri',
|
||||
channel_id: WEBCHANNEL_ID
|
||||
},
|
||||
/NS_ERROR_MALFORMED_URI/);
|
||||
|
||||
validationHelper({
|
||||
content_uri: URL_STRING
|
||||
},
|
||||
'Error: Missing \'channel_id\' option');
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_profile_image_change_message() {
|
||||
var mockMessage = {
|
||||
command: "profile:change",
|
||||
data: { uid: "foo" }
|
||||
};
|
||||
|
||||
makeObserver(ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
|
||||
do_check_eq(data, "foo");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
var channel = new FxAccountsWebChannel({
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
content_uri: URL_STRING
|
||||
});
|
||||
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
});
|
||||
|
||||
add_test(function test_login_message() {
|
||||
let mockMessage = {
|
||||
command: 'fxaccounts:login',
|
||||
data: { email: 'testuser@testuser.com' }
|
||||
};
|
||||
|
||||
let channel = new FxAccountsWebChannel({
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
content_uri: URL_STRING,
|
||||
helpers: {
|
||||
login: function (accountData) {
|
||||
do_check_eq(accountData.email, 'testuser@testuser.com');
|
||||
run_next_test();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
});
|
||||
|
||||
add_test(function test_can_link_account_message() {
|
||||
let mockMessage = {
|
||||
command: 'fxaccounts:can_link_account',
|
||||
data: { email: 'testuser@testuser.com' }
|
||||
};
|
||||
|
||||
let channel = new FxAccountsWebChannel({
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
content_uri: URL_STRING,
|
||||
helpers: {
|
||||
shouldAllowRelink: function (email) {
|
||||
do_check_eq(email, 'testuser@testuser.com');
|
||||
run_next_test();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
});
|
||||
|
||||
add_test(function test_unrecognized_message() {
|
||||
let mockMessage = {
|
||||
command: 'fxaccounts:unrecognized',
|
||||
data: {}
|
||||
};
|
||||
|
||||
let channel = new FxAccountsWebChannel({
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
content_uri: URL_STRING
|
||||
});
|
||||
|
||||
// no error is expected.
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
|
||||
add_test(function test_helpers_should_allow_relink_same_email() {
|
||||
let helpers = new FxAccountsWebChannelHelpers();
|
||||
|
||||
helpers.setPreviousAccountNameHashPref('testuser@testuser.com');
|
||||
do_check_true(helpers.shouldAllowRelink('testuser@testuser.com'));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_helpers_should_allow_relink_different_email() {
|
||||
let helpers = new FxAccountsWebChannelHelpers();
|
||||
|
||||
helpers.setPreviousAccountNameHashPref('testuser@testuser.com');
|
||||
|
||||
helpers._promptForRelink = (acctName) => {
|
||||
return acctName === 'allowed_to_relink@testuser.com';
|
||||
};
|
||||
|
||||
do_check_true(helpers.shouldAllowRelink('allowed_to_relink@testuser.com'));
|
||||
do_check_false(helpers.shouldAllowRelink('not_allowed_to_relink@testuser.com'));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_helpers_login_without_customize_sync() {
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
fxAccounts: {
|
||||
setSignedInUser: function(accountData) {
|
||||
// ensure fxAccounts is informed of the new user being signed in.
|
||||
do_check_eq(accountData.email, 'testuser@testuser.com');
|
||||
|
||||
// verifiedCanLinkAccount should be stripped in the data.
|
||||
do_check_false('verifiedCanLinkAccount' in accountData);
|
||||
|
||||
// the customizeSync pref should not update
|
||||
do_check_false(helpers.getShowCustomizeSyncPref());
|
||||
|
||||
// previously signed in user preference is updated.
|
||||
do_check_eq(helpers.getPreviousAccountNameHashPref(), helpers.sha256('testuser@testuser.com'));
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// the show customize sync pref should stay the same
|
||||
helpers.setShowCustomizeSyncPref(false);
|
||||
|
||||
// ensure the previous account pref is overwritten.
|
||||
helpers.setPreviousAccountNameHashPref('lastuser@testuser.com');
|
||||
|
||||
helpers.login({
|
||||
email: 'testuser@testuser.com',
|
||||
verifiedCanLinkAccount: true,
|
||||
customizeSync: false
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_helpers_login_with_customize_sync() {
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
fxAccounts: {
|
||||
setSignedInUser: function(accountData) {
|
||||
// ensure fxAccounts is informed of the new user being signed in.
|
||||
do_check_eq(accountData.email, 'testuser@testuser.com');
|
||||
|
||||
// customizeSync should be stripped in the data.
|
||||
do_check_false('customizeSync' in accountData);
|
||||
|
||||
// the customizeSync pref should not update
|
||||
do_check_true(helpers.getShowCustomizeSyncPref());
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// the customize sync pref should be overwritten
|
||||
helpers.setShowCustomizeSyncPref(false);
|
||||
|
||||
helpers.login({
|
||||
email: 'testuser@testuser.com',
|
||||
verifiedCanLinkAccount: true,
|
||||
customizeSync: true
|
||||
});
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function makeObserver(aObserveTopic, aObserveFunc) {
|
||||
let callback = function (aSubject, aTopic, aData) {
|
||||
log.debug("observed " + aTopic + " " + aData);
|
||||
if (aTopic == aObserveTopic) {
|
||||
removeMe();
|
||||
aObserveFunc(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
|
||||
function removeMe() {
|
||||
log.debug("removing observer for " + aObserveTopic);
|
||||
Services.obs.removeObserver(callback, aObserveTopic);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(callback, aObserveTopic, false);
|
||||
return removeMe;
|
||||
}
|
||||
|
||||
function validationHelper(params, expected) {
|
||||
try {
|
||||
new FxAccountsWebChannel(params);
|
||||
} catch (e) {
|
||||
if (typeof expected === 'string') {
|
||||
return do_check_eq(e.toString(), expected);
|
||||
} else {
|
||||
return do_check_true(e.toString().match(expected));
|
||||
}
|
||||
}
|
||||
throw new Error("Validation helper error");
|
||||
}
|
@ -18,5 +18,5 @@ reason = FxAccountsManager is only available for B2G for now
|
||||
[test_oauth_tokens.js]
|
||||
[test_oauth_token_storage.js]
|
||||
[test_profile_client.js]
|
||||
[test_profile_channel.js]
|
||||
[test_web_channel.js]
|
||||
[test_profile.js]
|
||||
|
@ -246,6 +246,7 @@ user_pref("identity.fxaccounts.remote.signup.uri", "https://%(server)s/fxa-signu
|
||||
user_pref("identity.fxaccounts.remote.force_auth.uri", "https://%(server)s/fxa-force-auth");
|
||||
user_pref("identity.fxaccounts.remote.signin.uri", "https://%(server)s/fxa-signin");
|
||||
user_pref("identity.fxaccounts.settings.uri", "https://%(server)s/fxa-settings");
|
||||
user_pref('identity.fxaccounts.remote.webchannel.uri', 'https://%(server)s/');
|
||||
|
||||
// Enable logging of APZ test data (see bug 961289).
|
||||
user_pref('apz.test.logging_enabled', true);
|
||||
|
Loading…
Reference in New Issue
Block a user