mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1138590 - Create a WebChannel for receiving FxA profile change notifications. r=markh
This commit is contained in:
parent
e8ffe73b99
commit
69338cfeaf
@ -12,6 +12,7 @@ support-files =
|
||||
browser_bug678392-2.html
|
||||
browser_bug970746.xhtml
|
||||
browser_fxa_oauth.html
|
||||
browser_fxa_profile_channel.html
|
||||
browser_registerProtocolHandler_notification.html
|
||||
browser_ssl_error_reports_content.js
|
||||
browser_star_hsts.sjs
|
||||
@ -319,6 +320,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_gestureSupport.js]
|
||||
skip-if = e10s # Bug 863514 - no gesture support.
|
||||
[browser_getshortcutoruri.js]
|
||||
|
@ -0,0 +1,26 @@
|
||||
<!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:image:change",
|
||||
data: {
|
||||
uid: "abc123",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,90 @@
|
||||
/* 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.ONPROFILE_IMAGE_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();
|
||||
});
|
||||
}
|
@ -90,6 +90,8 @@ exports.ONLOGOUT_NOTIFICATION = "fxaccounts:onlogout";
|
||||
// Internal to services/fxaccounts only
|
||||
exports.ON_FXA_UPDATE_NOTIFICATION = "fxaccounts:update";
|
||||
|
||||
exports.ONPROFILE_IMAGE_CHANGE_NOTIFICATION = "fxaccounts:profileimagechange";
|
||||
|
||||
// UI Requests.
|
||||
exports.UI_REQUEST_SIGN_IN_FLOW = "signInFlow";
|
||||
exports.UI_REQUEST_REFRESH_AUTH = "refreshAuthentication";
|
||||
@ -97,6 +99,9 @@ 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";
|
||||
|
||||
// Server errno.
|
||||
// From https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format
|
||||
exports.ERRNO_ACCOUNT_ALREADY_EXISTS = 101;
|
||||
|
118
services/fxaccounts/FxAccountsProfileChannel.jsm
Normal file
118
services/fxaccounts/FxAccountsProfileChannel.jsm
Normal file
@ -0,0 +1,118 @@
|
||||
/* 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_IMAGE_CHANGE_COMMAND = "profile:image: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_IMAGE_CHANGE_COMMAND:
|
||||
Services.obs.notifyObservers(null, ONPROFILE_IMAGE_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);
|
||||
}
|
||||
|
||||
};
|
@ -16,6 +16,7 @@ EXTRA_JS_MODULES += [
|
||||
'FxAccountsCommon.js',
|
||||
'FxAccountsOAuthClient.jsm',
|
||||
'FxAccountsOAuthGrantClient.jsm',
|
||||
'FxAccountsProfileChannel.jsm',
|
||||
'FxAccountsProfileClient.jsm',
|
||||
]
|
||||
|
||||
|
75
services/fxaccounts/tests/xpcshell/test_profile_channel.js
Normal file
75
services/fxaccounts/tests/xpcshell/test_profile_channel.js
Normal file
@ -0,0 +1,75 @@
|
||||
/* 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:image:change",
|
||||
data: { uid: "foo" }
|
||||
};
|
||||
|
||||
makeObserver(ONPROFILE_IMAGE_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");
|
||||
}
|
@ -15,3 +15,4 @@ reason = FxAccountsManager is only available for B2G for now
|
||||
[test_oauth_client.js]
|
||||
[test_oauth_grant_client.js]
|
||||
[test_profile_client.js]
|
||||
[test_profile_channel.js]
|
||||
|
Loading…
Reference in New Issue
Block a user