mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 1308038 - Add handshake capability to share state with FxA. r=markh, r=rkelly
This commit is contained in:
parent
ede9469c8a
commit
7a827756f9
@ -34,6 +34,7 @@ const COMMAND_LOGOUT = "fxaccounts:logout";
|
||||
const COMMAND_DELETE = "fxaccounts:delete";
|
||||
const COMMAND_SYNC_PREFERENCES = "fxaccounts:sync_preferences";
|
||||
const COMMAND_CHANGE_PASSWORD = "fxaccounts:change_password";
|
||||
const COMMAND_FXA_STATUS = "fxaccounts:fxa_status";
|
||||
|
||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||
|
||||
@ -173,6 +174,22 @@ this.FxAccountsWebChannel.prototype = {
|
||||
this._helpers.changePassword(data).catch(error =>
|
||||
this._sendError(error, message, sendingContext));
|
||||
break;
|
||||
case COMMAND_FXA_STATUS:
|
||||
log.debug("fxa_status received");
|
||||
|
||||
const service = data && data.service;
|
||||
this._helpers.getFxaStatus(service, sendingContext)
|
||||
.then(fxaStatus => {
|
||||
let response = {
|
||||
command,
|
||||
messageId: message.messageId,
|
||||
data: fxaStatus
|
||||
};
|
||||
this._channel.send(response, sendingContext);
|
||||
}).catch(error =>
|
||||
this._sendError(error, message, sendingContext)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
log.warn("Unrecognized FxAccountsWebChannel command", command);
|
||||
break;
|
||||
@ -297,7 +314,7 @@ this.FxAccountsWebChannelHelpers.prototype = {
|
||||
*/
|
||||
logout(uid) {
|
||||
return fxAccounts.getSignedInUser().then(userData => {
|
||||
if (userData.uid === uid) {
|
||||
if (userData && userData.uid === uid) {
|
||||
// true argument is `localOnly`, because server-side stuff
|
||||
// has already been taken care of by the content server
|
||||
return fxAccounts.signOut(true);
|
||||
@ -306,6 +323,71 @@ this.FxAccountsWebChannelHelpers.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if `sendingContext` is in private browsing mode.
|
||||
*/
|
||||
isPrivateBrowsingMode(sendingContext) {
|
||||
if (!sendingContext ||
|
||||
!sendingContext.browser ||
|
||||
!sendingContext.browser.docShell ||
|
||||
sendingContext.browser.docShell.usePrivateBrowsing === undefined) {
|
||||
log.error("Unable to check for private browsing mode, assuming true");
|
||||
return true;
|
||||
}
|
||||
|
||||
const isPrivateBrowsing = sendingContext.browser.docShell.usePrivateBrowsing;
|
||||
log.debug("is private browsing", isPrivateBrowsing);
|
||||
return isPrivateBrowsing;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether sending fxa_status data should be allowed.
|
||||
*/
|
||||
shouldAllowFxaStatus(service, sendingContext) {
|
||||
// Return user data for any service in non-PB mode. In PB mode,
|
||||
// only return user data if service==="sync".
|
||||
//
|
||||
// This behaviour allows users to click the "Manage Account"
|
||||
// link from about:preferences#sync while in PB mode and things
|
||||
// "just work". While in non-PB mode, users can sign into
|
||||
// Pocket w/o entering their password a 2nd time, while in PB
|
||||
// mode they *will* have to enter their email/password again.
|
||||
//
|
||||
// The difference in behaviour is to try to match user
|
||||
// expectations as to what is and what isn't part of the browser.
|
||||
// Sync is viewed as an integral part of the browser, interacting
|
||||
// with FxA as part of a Sync flow should work all the time. If
|
||||
// Sync is broken in PB mode, users will think Firefox is broken.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1323853
|
||||
log.debug("service", service);
|
||||
return !this.isPrivateBrowsingMode(sendingContext) || service === "sync";
|
||||
},
|
||||
|
||||
/**
|
||||
* Get fxa_status information. Resolves to { signedInUser: <user_data> }.
|
||||
* If returning status information is not allowed or no user is signed into
|
||||
* Sync, `user_data` will be null.
|
||||
*/
|
||||
async getFxaStatus(service, sendingContext) {
|
||||
let signedInUser = null;
|
||||
|
||||
if (this.shouldAllowFxaStatus(service, sendingContext)) {
|
||||
const userData = await this._fxAccounts.getSignedInUser();
|
||||
if (userData) {
|
||||
signedInUser = {
|
||||
email: userData.email,
|
||||
sessionToken: userData.sessionToken,
|
||||
uid: userData.uid,
|
||||
verified: userData.verified
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
signedInUser
|
||||
};
|
||||
},
|
||||
|
||||
changePassword(credentials) {
|
||||
// If |credentials| has fields that aren't handled by accounts storage,
|
||||
// updateUserAccountData will throw - mainly to prevent errors in code
|
||||
|
@ -10,7 +10,11 @@ const { FxAccountsWebChannel, FxAccountsWebChannelHelpers } =
|
||||
const URL_STRING = "https://example.com";
|
||||
|
||||
const mockSendingContext = {
|
||||
browser: {},
|
||||
browser: {
|
||||
docShell: {
|
||||
usePrivateBrowsing: false
|
||||
}
|
||||
},
|
||||
principal: {},
|
||||
eventTarget: {}
|
||||
};
|
||||
@ -235,6 +239,51 @@ add_test(function test_sync_preferences_message() {
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
});
|
||||
|
||||
add_test(function test_fxa_status_message() {
|
||||
let mockMessage = {
|
||||
command: "fxaccounts:fxa_status",
|
||||
messageId: 123,
|
||||
data: {
|
||||
service: "sync"
|
||||
}
|
||||
};
|
||||
|
||||
let channel = new FxAccountsWebChannel({
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
content_uri: URL_STRING,
|
||||
helpers: {
|
||||
async getFxaStatus() {
|
||||
return {
|
||||
signedInUser: {
|
||||
email: "testuser@testuser.com",
|
||||
sessionToken: "session-token",
|
||||
uid: "uid",
|
||||
verified: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
channel._channel = {
|
||||
send(response, sendingContext) {
|
||||
do_check_eq(response.command, "fxaccounts:fxa_status");
|
||||
do_check_eq(response.messageId, 123);
|
||||
|
||||
let signedInUser = response.data.signedInUser;
|
||||
do_check_true(!!signedInUser);
|
||||
do_check_eq(signedInUser.email, "testuser@testuser.com");
|
||||
do_check_eq(signedInUser.sessionToken, "session-token");
|
||||
do_check_eq(signedInUser.uid, "uid");
|
||||
do_check_eq(signedInUser.verified, true);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
};
|
||||
|
||||
channel._channelCallback(WEBCHANNEL_ID, mockMessage, mockSendingContext);
|
||||
});
|
||||
|
||||
add_test(function test_unrecognized_message() {
|
||||
let mockMessage = {
|
||||
command: "fxaccounts:unrecognized",
|
||||
@ -384,6 +433,242 @@ add_test(function test_helpers_open_sync_preferences() {
|
||||
helpers.openSyncPreferences(mockBrowser, "fxa:verification_complete");
|
||||
});
|
||||
|
||||
|
||||
add_task(function* test_helpers_getFxaStatus_allowed_signedInUser() {
|
||||
let wasCalled = {
|
||||
getSignedInUser: false,
|
||||
shouldAllowFxaStatus: false
|
||||
};
|
||||
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
fxAccounts: {
|
||||
getSignedInUser() {
|
||||
wasCalled.getSignedInUser = true;
|
||||
return Promise.resolve({
|
||||
email: "testuser@testuser.com",
|
||||
kA: "kA",
|
||||
kb: "kB",
|
||||
sessionToken: "sessionToken",
|
||||
uid: "uid",
|
||||
verified: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
helpers.shouldAllowFxaStatus = (service, sendingContext) => {
|
||||
wasCalled.shouldAllowFxaStatus = true;
|
||||
do_check_eq(service, "sync");
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return helpers.getFxaStatus("sync", mockSendingContext)
|
||||
.then(fxaStatus => {
|
||||
do_check_true(!!fxaStatus);
|
||||
do_check_true(wasCalled.getSignedInUser);
|
||||
do_check_true(wasCalled.shouldAllowFxaStatus);
|
||||
|
||||
do_check_true(!!fxaStatus.signedInUser);
|
||||
let {signedInUser} = fxaStatus;
|
||||
|
||||
do_check_eq(signedInUser.email, "testuser@testuser.com");
|
||||
do_check_eq(signedInUser.sessionToken, "sessionToken");
|
||||
do_check_eq(signedInUser.uid, "uid");
|
||||
do_check_true(signedInUser.verified);
|
||||
|
||||
// These properties are filtered and should not
|
||||
// be returned to the requester.
|
||||
do_check_false("kA" in signedInUser);
|
||||
do_check_false("kB" in signedInUser);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_getFxaStatus_allowed_no_signedInUser() {
|
||||
let wasCalled = {
|
||||
getSignedInUser: false,
|
||||
shouldAllowFxaStatus: false
|
||||
};
|
||||
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
fxAccounts: {
|
||||
getSignedInUser() {
|
||||
wasCalled.getSignedInUser = true;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
helpers.shouldAllowFxaStatus = (service, sendingContext) => {
|
||||
wasCalled.shouldAllowFxaStatus = true;
|
||||
do_check_eq(service, "sync");
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return helpers.getFxaStatus("sync", mockSendingContext)
|
||||
.then(fxaStatus => {
|
||||
do_check_true(!!fxaStatus);
|
||||
do_check_true(wasCalled.getSignedInUser);
|
||||
do_check_true(wasCalled.shouldAllowFxaStatus);
|
||||
|
||||
do_check_null(fxaStatus.signedInUser);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_getFxaStatus_not_allowed() {
|
||||
let wasCalled = {
|
||||
getSignedInUser: false,
|
||||
shouldAllowFxaStatus: false
|
||||
};
|
||||
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
fxAccounts: {
|
||||
getSignedInUser() {
|
||||
wasCalled.getSignedInUser = true;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
helpers.shouldAllowFxaStatus = (service, sendingContext) => {
|
||||
wasCalled.shouldAllowFxaStatus = true;
|
||||
do_check_eq(service, "sync");
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return helpers.getFxaStatus("sync", mockSendingContext)
|
||||
.then(fxaStatus => {
|
||||
do_check_true(!!fxaStatus);
|
||||
do_check_false(wasCalled.getSignedInUser);
|
||||
do_check_true(wasCalled.shouldAllowFxaStatus);
|
||||
|
||||
do_check_null(fxaStatus.signedInUser);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_sync_service_not_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("sync", mockSendingContext);
|
||||
do_check_true(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_oauth_service_not_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("dcdb5ae7add825d2", mockSendingContext);
|
||||
do_check_true(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_no_service_not_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("", mockSendingContext);
|
||||
do_check_true(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_sync_service_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("sync", mockSendingContext);
|
||||
do_check_true(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_oauth_service_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("dcdb5ae7add825d2", mockSendingContext);
|
||||
do_check_false(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_shouldAllowFxaStatus_no_service_private_browsing() {
|
||||
let wasCalled = {
|
||||
isPrivateBrowsingMode: false
|
||||
};
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
|
||||
helpers.isPrivateBrowsingMode = (sendingContext) => {
|
||||
wasCalled.isPrivateBrowsingMode = true;
|
||||
do_check_eq(sendingContext, mockSendingContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
let shouldAllowFxaStatus = helpers.shouldAllowFxaStatus("", mockSendingContext);
|
||||
do_check_false(shouldAllowFxaStatus);
|
||||
do_check_true(wasCalled.isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_isPrivateBrowsingMode_private_browsing() {
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
mockSendingContext.browser.docShell.usePrivateBrowsing = true;
|
||||
|
||||
let isPrivateBrowsingMode = helpers.isPrivateBrowsingMode(mockSendingContext);
|
||||
do_check_true(isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_isPrivateBrowsingMode_private_browsing() {
|
||||
let helpers = new FxAccountsWebChannelHelpers({});
|
||||
mockSendingContext.browser.docShell.usePrivateBrowsing = false;
|
||||
|
||||
let isPrivateBrowsingMode = helpers.isPrivateBrowsingMode(mockSendingContext);
|
||||
do_check_false(isPrivateBrowsingMode);
|
||||
});
|
||||
|
||||
add_task(function* test_helpers_change_password() {
|
||||
let wasCalled = {
|
||||
updateUserAccountData: false,
|
||||
|
Loading…
Reference in New Issue
Block a user