mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 898706 remove frameworker and all associated code and tests, r=markh
This commit is contained in:
parent
b582bcefb4
commit
c3a25096a7
@ -69,9 +69,6 @@
|
||||
config.tryAgainCallback = loadQueryURL;
|
||||
config.queryURL = url;
|
||||
break;
|
||||
case "workerFailure":
|
||||
config.tryAgainCallback = reloadProvider;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -104,20 +101,8 @@
|
||||
}
|
||||
|
||||
function reloadProvider() {
|
||||
// Just incase the current provider *isn't* in a frameworker-error
|
||||
// state, reload the current one.
|
||||
let provider = Social._getProviderFromOrigin(config.origin);
|
||||
provider.reload();
|
||||
// If the problem is a frameworker-error, it may be that the child
|
||||
// process crashed - and if that happened, then *all* providers in that
|
||||
// process will have crashed. However, only the current provider is
|
||||
// likely to have the error surfaced in the UI - so we reload *all*
|
||||
// providers that are in a frameworker-error state.
|
||||
for (let provider of Social.providers) {
|
||||
if (provider.enabled && provider.errorState == "frameworker-error") {
|
||||
provider.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parseQueryString();
|
||||
|
@ -65,8 +65,6 @@ SocialUI = {
|
||||
mm.loadFrameScript("chrome://browser/content/social-content.js", true);
|
||||
|
||||
Services.obs.addObserver(this, "social:ambient-notification-changed", false);
|
||||
Services.obs.addObserver(this, "social:profile-changed", false);
|
||||
Services.obs.addObserver(this, "social:frameworker-error", false);
|
||||
Services.obs.addObserver(this, "social:providers-changed", false);
|
||||
Services.obs.addObserver(this, "social:provider-reload", false);
|
||||
Services.obs.addObserver(this, "social:provider-enabled", false);
|
||||
@ -76,6 +74,7 @@ SocialUI = {
|
||||
|
||||
CustomizableUI.addListener(this);
|
||||
SocialActivationListener.init();
|
||||
messageManager.addMessageListener("Social:Notification", this);
|
||||
|
||||
// menupopups that list social providers. we only populate them when shown,
|
||||
// and if it has not been done already.
|
||||
@ -100,8 +99,6 @@ SocialUI = {
|
||||
SocialSidebar.saveWindowState();
|
||||
|
||||
Services.obs.removeObserver(this, "social:ambient-notification-changed");
|
||||
Services.obs.removeObserver(this, "social:profile-changed");
|
||||
Services.obs.removeObserver(this, "social:frameworker-error");
|
||||
Services.obs.removeObserver(this, "social:providers-changed");
|
||||
Services.obs.removeObserver(this, "social:provider-reload");
|
||||
Services.obs.removeObserver(this, "social:provider-enabled");
|
||||
@ -110,6 +107,7 @@ SocialUI = {
|
||||
Services.prefs.removeObserver("social.toast-notifications.enabled", this);
|
||||
CustomizableUI.removeListener(this);
|
||||
SocialActivationListener.uninit();
|
||||
messageManager.removeMessageListener("Social:Notification", this);
|
||||
|
||||
document.getElementById("viewSidebarMenu").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
|
||||
document.getElementById("social-statusarea-popup").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
|
||||
@ -117,6 +115,15 @@ SocialUI = {
|
||||
this._initialized = false;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (aMessage.name == "Social:Notification") {
|
||||
let provider = Social._getProviderFromOrigin(aMessage.data.origin);
|
||||
if (provider) {
|
||||
provider.setAmbientNotification(aMessage.data.detail);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
observe: function SocialUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "social:provider-enabled":
|
||||
@ -149,17 +156,6 @@ SocialUI = {
|
||||
case "social:ambient-notification-changed":
|
||||
SocialStatus.updateButton(data);
|
||||
break;
|
||||
case "social:profile-changed":
|
||||
// make sure anything that happens here only affects the provider for
|
||||
// which the profile is changing, and that anything we call actually
|
||||
// needs to change based on profile data.
|
||||
SocialStatus.updateButton(data);
|
||||
break;
|
||||
case "social:frameworker-error":
|
||||
if (this.enabled && SocialSidebar.provider && SocialSidebar.provider.origin == data) {
|
||||
SocialSidebar.loadFrameworkerFailure();
|
||||
}
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
if (data == "social.toast-notifications.enabled") {
|
||||
SocialSidebar.updateToggleNotifications();
|
||||
@ -218,17 +214,12 @@ SocialUI = {
|
||||
|
||||
get enabled() {
|
||||
// Returns whether social is enabled *for this window*.
|
||||
if (this._chromeless || PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
if (this._chromeless)
|
||||
return false;
|
||||
return Social.providers.length > 0;
|
||||
},
|
||||
|
||||
canShareOrMarkPage: function(aURI) {
|
||||
// Bug 898706 we do not enable social in private sessions since frameworker
|
||||
// would be shared between private and non-private windows
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
return false;
|
||||
|
||||
return (aURI && (aURI.schemeIs('http') || aURI.schemeIs('https')));
|
||||
},
|
||||
|
||||
@ -287,10 +278,6 @@ SocialActivationListener = {
|
||||
options = { bypassContentCheck: true, bypassInstallPanel: true };
|
||||
}
|
||||
|
||||
// If we are in PB mode, we silently do nothing (bug 829404 exists to
|
||||
// do something sensible here...)
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
return;
|
||||
Social.installProvider(data, function(manifest) {
|
||||
Social.activateFromOrigin(manifest.origin, function(provider) {
|
||||
if (provider.sidebarURL) {
|
||||
@ -950,16 +937,6 @@ SocialSidebar = {
|
||||
|
||||
_unloadTimeoutId: 0,
|
||||
|
||||
loadFrameworkerFailure: function() {
|
||||
if (this.provider && this.provider.errorState == "frameworker-error") {
|
||||
// we have to explicitly load this error page since it is not being
|
||||
// handled via the normal error page paths.
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
sbrowser.setAttribute("src", "about:socialerror?mode=workerFailure&origin=" +
|
||||
encodeURIComponent(this.provider.origin));
|
||||
}
|
||||
},
|
||||
|
||||
_provider: null,
|
||||
ensureProvider: function() {
|
||||
if (this._provider)
|
||||
@ -1241,8 +1218,8 @@ SocialStatus = {
|
||||
let iconNames = Object.keys(icons);
|
||||
let notif = icons[iconNames[0]];
|
||||
|
||||
// The image and tooltip need to be updated for both
|
||||
// ambient notification and profile changes.
|
||||
// The image and tooltip need to be updated for
|
||||
// ambient notification changes.
|
||||
let iconURL = provider.icon32URL || provider.iconURL;
|
||||
let tooltiptext;
|
||||
if (!notif || !widget.areaType) {
|
||||
|
@ -35,6 +35,15 @@ addEventListener("DOMTitleChanged", function(e) {
|
||||
});
|
||||
var gHookedWindowCloseForPanelClose = false;
|
||||
|
||||
addEventListener("Social:Notification", function(event) {
|
||||
let frame = docShell.chromeEventHandler;
|
||||
let origin = frame.getAttribute("origin");
|
||||
sendAsyncMessage("Social:Notification", {
|
||||
"origin": origin,
|
||||
"detail": JSON.parse(event.detail)
|
||||
});
|
||||
});
|
||||
|
||||
// Error handling class used to listen for network errors in the social frames
|
||||
// and replace them with a social-specific error page
|
||||
SocialErrorListener = {
|
||||
@ -209,6 +218,8 @@ SocialErrorListener = {
|
||||
|
||||
onStateChange(aWebProgress, aRequest, aState, aStatus) {
|
||||
let failure = false;
|
||||
if ((aState & Ci.nsIWebProgressListener.STATE_IS_REQUEST))
|
||||
return;
|
||||
if ((aState & Ci.nsIWebProgressListener.STATE_STOP)) {
|
||||
if (aRequest instanceof Ci.nsIHttpChannel) {
|
||||
try {
|
||||
|
@ -246,7 +246,7 @@
|
||||
<body><![CDATA[
|
||||
// we always set the src on click if it has not been set for this tab,
|
||||
// but we only want to open the panel if it was previously annotated.
|
||||
let openPanel = this.isMarked || aOpenPanel || !this.provider.haveLoggedInUser();
|
||||
let openPanel = this.isMarked || aOpenPanel;
|
||||
let src = this.content.getAttribute("src");
|
||||
if (!src || src == "about:blank") {
|
||||
this.loadPanel();
|
||||
|
@ -23,8 +23,6 @@ support-files =
|
||||
social_postActivation.html
|
||||
social_sidebar.html
|
||||
social_sidebar_empty.html
|
||||
social_window.html
|
||||
social_worker.js
|
||||
unchecked.jpg
|
||||
|
||||
[browser_aboutHome_activation.js]
|
||||
@ -44,12 +42,6 @@ skip-if = (os == 'linux' && e10s) # Bug 1072669 context menu relies on target el
|
||||
[browser_social_marks.js]
|
||||
[browser_social_marks_context.js]
|
||||
[browser_social_multiprovider.js]
|
||||
[browser_social_multiworker.js]
|
||||
[browser_social_perwindowPB.js]
|
||||
[browser_social_sidebar.js]
|
||||
[browser_social_status.js]
|
||||
skip-if = true # Bug 1245800 'onoffline' and 'ononline' not defined JS errors
|
||||
[browser_social_window.js]
|
||||
[browser_social_workercrash.js]
|
||||
#skip-if = !crashreporter
|
||||
skip-if = true # Bug 1060813 - frequent leaks on all platforms
|
||||
|
@ -18,7 +18,6 @@ var manifestUpgrade = { // used for testing install
|
||||
name: "provider 3",
|
||||
origin: "https://test2.example.com",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://test2.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://test2.example.com/browser/browser/base/content/test/general/moz.png",
|
||||
version: "1.0"
|
||||
};
|
||||
@ -211,72 +210,5 @@ var tests = {
|
||||
Social.uninstallProvider(addonManifest.origin);
|
||||
});
|
||||
});
|
||||
},
|
||||
testUpgradeProviderFromWorker: function(next) {
|
||||
// add the provider, change the pref, add it again. The provider at that
|
||||
// point should be upgraded
|
||||
let activationURL = manifestUpgrade.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||
ensureEventFired(PopupNotifications.panel, "popupshown").then(() => {
|
||||
let panel = document.getElementById("servicesInstall-notification");
|
||||
info("servicesInstall-notification panel opened");
|
||||
panel.button.click();
|
||||
});
|
||||
|
||||
addTab(activationURL, function(tab) {
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
let installFrom = doc.nodePrincipal.origin;
|
||||
Services.prefs.setCharPref("social.whitelist", installFrom);
|
||||
let data = {
|
||||
origin: installFrom,
|
||||
url: doc.location.href,
|
||||
manifest: manifestUpgrade,
|
||||
window: window
|
||||
}
|
||||
Social.installProvider(data, function(addonManifest) {
|
||||
SocialService.enableProvider(addonManifest.origin, function(provider) {
|
||||
is(provider.manifest.version, 1, "manifest version is 1");
|
||||
|
||||
// watch for the provider-update and test the new version
|
||||
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||
if (topic != "provider-update")
|
||||
return;
|
||||
// The worker will have reloaded and the current provider instance
|
||||
// disabled, removed from the provider list. We have a reference
|
||||
// here, check it is is disabled.
|
||||
is(provider.enabled, false, "old provider instance is disabled")
|
||||
is(origin, addonManifest.origin, "provider manifest updated")
|
||||
SocialService.unregisterProviderListener(providerListener);
|
||||
|
||||
// Get the new provider instance, fetch the manifest via workerapi
|
||||
// and validate that data as well.
|
||||
let p = Social._getProviderFromOrigin(origin);
|
||||
is(p.manifest.version, 2, "manifest version is 2");
|
||||
let port = p.getWorkerPort();
|
||||
ok(port, "got a new port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "social.manifest":
|
||||
let manifest = e.data.data;
|
||||
is(manifest.version, 2, "manifest version is 2");
|
||||
port.close();
|
||||
Social.uninstallProvider(origin, function() {
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
ensureBrowserTabClosed(tab).then(next);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.postMessage({topic: "manifest-get"});
|
||||
|
||||
});
|
||||
|
||||
let port = provider.getWorkerPort();
|
||||
port.postMessage({topic: "worker.update", data: true});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -13,14 +13,12 @@ var manifest = { // normal provider
|
||||
name: "provider ok",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
var manifest_bad = { // normal provider
|
||||
name: "provider blocked",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,6 @@ var baseURL = "https://example.com/browser/browser/base/content/test/social/";
|
||||
var manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png",
|
||||
shareURL: "https://example.com/browser/browser/base/content/test/social/share.html"
|
||||
};
|
||||
@ -24,11 +23,11 @@ function sendActivationEvent(subframe) {
|
||||
|
||||
function promiseShareFrameEvent(iframe, eventName) {
|
||||
let deferred = Promise.defer();
|
||||
iframe.addEventListener(eventName, function load() {
|
||||
iframe.addEventListener(eventName, function load(event) {
|
||||
info("page load is " + iframe.contentDocument.location.href);
|
||||
if (iframe.contentDocument.location.href != "data:text/plain;charset=utf8,") {
|
||||
iframe.removeEventListener(eventName, load, true);
|
||||
deferred.resolve();
|
||||
deferred.resolve(event);
|
||||
}
|
||||
}, true);
|
||||
return deferred.promise;
|
||||
@ -37,7 +36,17 @@ function promiseShareFrameEvent(iframe, eventName) {
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
Services.prefs.setCharPref("social.shareDirectory", activationPage);
|
||||
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addEventListener("OpenGraphData", function (aEvent) {
|
||||
sendAsyncMessage("sharedata", aEvent.detail);
|
||||
}, true, true);
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
Services.prefs.clearUserPref("social.directories");
|
||||
Services.prefs.clearUserPref("social.shareDirectory");
|
||||
Services.prefs.clearUserPref("social.share.activationPanelEnabled");
|
||||
@ -174,40 +183,34 @@ var tests = {
|
||||
},
|
||||
testSharePage: function(next) {
|
||||
let provider = Social._getProviderFromOrigin(manifest.origin);
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
|
||||
let testTab;
|
||||
let testIndex = 0;
|
||||
let testData = corpus[testIndex++];
|
||||
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("sharedata", function handler(msg) {
|
||||
gBrowser.removeTab(testTab);
|
||||
hasoptions(testData.options, JSON.parse(msg.data));
|
||||
testData = corpus[testIndex++];
|
||||
if (testData) {
|
||||
executeSoon(runOneTest);
|
||||
} else {
|
||||
mm.removeMessageListener("sharedata", handler);
|
||||
SocialService.disableProvider(manifest.origin, next);
|
||||
}
|
||||
});
|
||||
|
||||
function runOneTest() {
|
||||
addTab(testData.url, function(tab) {
|
||||
testTab = tab;
|
||||
SocialShare.sharePage(manifest.origin);
|
||||
});
|
||||
}
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
gBrowser.removeTab(testTab);
|
||||
hasoptions(testData.options, e.data.result);
|
||||
testData = corpus[testIndex++];
|
||||
if (testData) {
|
||||
executeSoon(runOneTest);
|
||||
} else {
|
||||
SocialService.disableProvider(manifest.origin, next);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
executeSoon(runOneTest);
|
||||
},
|
||||
testShareMicroformats: function(next) {
|
||||
SocialService.addProvider(manifest, function(provider) {
|
||||
let port = provider.getWorkerPort();
|
||||
let target, testTab;
|
||||
|
||||
let expecting = JSON.stringify({
|
||||
@ -226,7 +229,7 @@ var tests = {
|
||||
}
|
||||
],
|
||||
"url": ["https://example.com/"],
|
||||
"price": ["£29.95"],
|
||||
"price": ["29.95"],
|
||||
"review": [{
|
||||
"value": "4.5 out of 5",
|
||||
"type": ["h-review"],
|
||||
@ -255,17 +258,13 @@ var tests = {
|
||||
}
|
||||
});
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
is(JSON.stringify(e.data.result), expecting, "microformats data ok");
|
||||
gBrowser.removeTab(testTab);
|
||||
SocialService.disableProvider(manifest.origin, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("sharedata", function handler(msg) {
|
||||
is(msg.data, expecting, "microformats data ok");
|
||||
gBrowser.removeTab(testTab);
|
||||
mm.removeMessageListener("sharedata", handler);
|
||||
SocialService.disableProvider(manifest.origin, next);
|
||||
});
|
||||
|
||||
let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
|
||||
addTab(url, function(tab) {
|
||||
@ -296,20 +295,13 @@ var tests = {
|
||||
}, () => {
|
||||
is(subframe.contentDocument.location.href, activationPage, "activation page loaded");
|
||||
promiseObserverNotified("social:provider-enabled").then(() => {
|
||||
let provider = Social._getProviderFromOrigin(manifest.origin);
|
||||
let port = provider.getWorkerPort();
|
||||
ok(!!port, "got port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
ok(true, "share completed");
|
||||
gBrowser.removeTab(testTab);
|
||||
SocialService.uninstallProvider(manifest.origin, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("sharedata", function handler(msg) {
|
||||
ok(true, "share completed");
|
||||
gBrowser.removeTab(testTab);
|
||||
mm.removeMessageListener("sharedata", handler);
|
||||
SocialService.uninstallProvider(manifest.origin, next);
|
||||
});
|
||||
});
|
||||
sendActivationEvent(subframe);
|
||||
}, "share panel did not open and load share page");
|
||||
|
@ -9,46 +9,30 @@ var manifests = [
|
||||
name: "provider@example.com",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?example.com",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider@test1",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?test1",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider@test2",
|
||||
origin: "https://test2.example.com",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?test2",
|
||||
workerURL: "https://test2.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
}
|
||||
];
|
||||
|
||||
var ports = [];
|
||||
function getProviderPort(provider) {
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
ports.push(port);
|
||||
return port;
|
||||
}
|
||||
var chatId = 0;
|
||||
function openChat(provider, callback) {
|
||||
function openChat(provider) {
|
||||
let deferred = Promise.defer();
|
||||
SocialSidebar.provider = provider;
|
||||
let chatUrl = provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
|
||||
let port = getProviderPort(provider);
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "got-chatbox-message") {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
let url = chatUrl + "?" + (chatId++);
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.postMessage({topic: "test-worker-chat", data: url});
|
||||
gURLsNotRemembered.push(url);
|
||||
return port;
|
||||
let url = chatUrl + "?id=" + (chatId++);
|
||||
makeChat("normal", "chat " + chatId, (cb) => { deferred.resolve(cb); });
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function windowHasChats(win) {
|
||||
@ -59,30 +43,32 @@ function test() {
|
||||
requestLongerTimeout(2); // only debug builds seem to need more time...
|
||||
waitForExplicitFinish();
|
||||
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addMessageListener("socialTest-CloseSelf", function(e) {
|
||||
content.close();
|
||||
});
|
||||
addEventListener("visibilitychange", function() {
|
||||
sendAsyncMessage("chatbox-visibility", content.document.hidden ? "hidden" : "shown");
|
||||
});
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
let oldwidth = window.outerWidth; // we futz with these, so we restore them
|
||||
let oldleft = window.screenX;
|
||||
window.moveTo(0, window.screenY)
|
||||
let postSubTest = function(cb) {
|
||||
// ensure ports are closed
|
||||
for (let port of ports) {
|
||||
port.close()
|
||||
ok(port._closed, "port closed");
|
||||
}
|
||||
ports = [];
|
||||
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
ok(chats.children.length == 0, "no chatty children left behind");
|
||||
cb();
|
||||
};
|
||||
runSocialTestWithProvider(manifests, function (finishcb) {
|
||||
ok(Social.enabled, "Social is enabled");
|
||||
ok(getProviderPort(Social.providers[0]), "provider 0 has port");
|
||||
ok(getProviderPort(Social.providers[1]), "provider 1 has port");
|
||||
ok(getProviderPort(Social.providers[2]), "provider 2 has port");
|
||||
SocialSidebar.show();
|
||||
runSocialTests(tests, undefined, postSubTest, function() {
|
||||
window.moveTo(oldleft, window.screenY)
|
||||
window.resizeTo(oldwidth, window.outerHeight);
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
@ -90,85 +76,29 @@ function test() {
|
||||
|
||||
var tests = {
|
||||
testOpenCloseChat: function(next) {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
openChatViaUser();
|
||||
break;
|
||||
case "got-chatbox-visibility":
|
||||
let selectedChat = chats.selectedChat || chats.lastElementChild;
|
||||
if (e.data.result == "hidden") {
|
||||
ok(true, "chatbox got minimized");
|
||||
selectedChat.toggle();
|
||||
} else if (e.data.result == "shown") {
|
||||
ok(true, "chatbox got shown");
|
||||
// close it now
|
||||
let content = selectedChat.content;
|
||||
content.addEventListener("unload", function chatUnload() {
|
||||
content.removeEventListener("unload", chatUnload, true);
|
||||
ok(true, "got chatbox unload on close");
|
||||
next();
|
||||
}, true);
|
||||
selectedChat.close();
|
||||
}
|
||||
break;
|
||||
case "got-chatbox-message":
|
||||
ok(true, "got chatbox message");
|
||||
ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result);
|
||||
selectedChat.toggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init", data: { id: 1 }});
|
||||
},
|
||||
testWorkerChatWindow: function(next) {
|
||||
const chatUrl = SocialSidebar.provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-chatbox-message":
|
||||
ok(true, "got a chat window opened");
|
||||
ok(chats.selectedChat, "chatbox from worker opened");
|
||||
while (chats.selectedChat) {
|
||||
chats.selectedChat.close();
|
||||
}
|
||||
ok(!chats.selectedChat, "chats are all closed");
|
||||
gURLsNotRemembered.push(chatUrl);
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(!chats.selectedChat, "chats are all closed");
|
||||
port.postMessage({topic: "test-worker-chat", data: chatUrl});
|
||||
},
|
||||
testCloseSelf: function(next) {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
openChatViaUser();
|
||||
break;
|
||||
case "got-chatbox-visibility":
|
||||
is(e.data.result, "shown", "chatbox shown");
|
||||
port.close(); // don't want any more visibility messages.
|
||||
let chat = chats.selectedChat;
|
||||
ok(chat.parentNode, "chat has a parent node before it is closed");
|
||||
// ask it to close itself.
|
||||
let mm = chat.content.messageManager;
|
||||
mm.sendAsyncMessage("Social:CustomEvent", { name: "socialTest-CloseSelf" });
|
||||
waitForCondition(() => !chat.parentNode, next, "chat should close");
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init", data: { id: 1 }});
|
||||
openChat(SocialSidebar.provider).then((cb) => {
|
||||
let smm = getGroupMessageManager("social");
|
||||
// Sometimes we'll get the initial shown visibility from opening the chat
|
||||
// box, so we ensure that we get hidden first.
|
||||
let minimized = false;
|
||||
smm.addMessageListener("chatbox-visibility", function handler(msg) {
|
||||
if (minimized && msg.data == "shown") {
|
||||
ok(true, "chatbox got shown");
|
||||
smm.removeMessageListener("chatbox-visibility", handler);
|
||||
// test the chatbox content closing itself
|
||||
promiseNodeRemoved(cb).then(next);
|
||||
let mm = cb.content.messageManager;
|
||||
mm.sendAsyncMessage("socialTest-CloseSelf", {});
|
||||
} else if (!minimized && msg.data == "hidden") {
|
||||
minimized = true;
|
||||
ok(true, "chatbox got minimized");
|
||||
// toggle to maximize chat
|
||||
cb.toggle();
|
||||
}
|
||||
});
|
||||
// toggle to minimize chat
|
||||
cb.toggle();
|
||||
});
|
||||
},
|
||||
|
||||
// Check what happens when you close the only visible chat.
|
||||
@ -178,8 +108,6 @@ var tests = {
|
||||
let num = 0;
|
||||
is(chatbar.childNodes.length, 0, "chatbar starting empty");
|
||||
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
port.postMessage({topic: "test-init"});
|
||||
|
||||
makeChat("normal", "first chat", function() {
|
||||
// got the first one.
|
||||
@ -209,8 +137,6 @@ var tests = {
|
||||
},
|
||||
|
||||
testShowWhenCollapsed: function(next) {
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
port.postMessage({topic: "test-init"});
|
||||
get3ChatsForCollapsing("normal", function(first, second, third) {
|
||||
let chatbar = getChatBar();
|
||||
chatbar.showChat(first);
|
||||
@ -218,91 +144,5 @@ var tests = {
|
||||
is(second.collapsed || third.collapsed, true, "one of the others should be collapsed");
|
||||
Task.spawn(closeAllChats).then(next);
|
||||
});
|
||||
},
|
||||
|
||||
testOnlyOneCallback: function(next) {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = getProviderPort(SocialSidebar.provider);
|
||||
let numOpened = 0;
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
port.postMessage({topic: "test-chatbox-open"});
|
||||
break;
|
||||
case "chatbox-opened":
|
||||
numOpened += 1;
|
||||
port.postMessage({topic: "ping"});
|
||||
break;
|
||||
case "pong":
|
||||
executeSoon(function() {
|
||||
is(numOpened, 1, "only got one open message");
|
||||
chats.selectedChat.close();
|
||||
next();
|
||||
});
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init", data: { id: 1 }});
|
||||
},
|
||||
|
||||
testMultipleProviderChat: function(next) {
|
||||
// test incomming chats from all providers
|
||||
let port0 = openChat(Social.providers[0], function() {
|
||||
let port1 = openChat(Social.providers[1], function() {
|
||||
let port2 = openChat(Social.providers[2], function() {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
waitForCondition(() => chats.children.length == Social.providers.length,
|
||||
function() {
|
||||
ok(true, "one chat window per provider opened");
|
||||
// test logout of a single provider
|
||||
port2.postMessage({topic: "test-logout"});
|
||||
waitForCondition(() => chats.children.length == Social.providers.length - 1,
|
||||
function() {
|
||||
Task.spawn(closeAllChats).then(next);
|
||||
},
|
||||
"chat window didn't close");
|
||||
}, "chat windows did not open");
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// XXX - note this must be the last test until we restore the login state
|
||||
// between tests...
|
||||
testCloseOnLogout: function(next) {
|
||||
const chatUrl = SocialSidebar.provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ports.push(port);
|
||||
ok(port, "provider has a port");
|
||||
let opened = false;
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
info("open first chat window");
|
||||
port.postMessage({topic: "test-worker-chat", data: chatUrl});
|
||||
break;
|
||||
case "got-chatbox-message":
|
||||
ok(true, "got a chat window opened");
|
||||
if (opened) {
|
||||
port.postMessage({topic: "test-logout"});
|
||||
waitForCondition(() => document.getElementById("pinnedchats").firstChild == null,
|
||||
function() {
|
||||
next();
|
||||
},
|
||||
"chat windows didn't close");
|
||||
} else {
|
||||
// open a second chat window
|
||||
opened = true;
|
||||
port.postMessage({topic: "test-worker-chat", data: chatUrl+"?id=1"});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// make sure a user profile is set for this provider as chat windows are
|
||||
// only closed on *change* of the profile data rather than merely setting
|
||||
// profile data.
|
||||
port.postMessage({topic: "test-set-profile"});
|
||||
port.postMessage({topic: "test-init"});
|
||||
}
|
||||
}
|
||||
|
@ -6,71 +6,10 @@ function isChatFocused(chat) {
|
||||
return getChatBar()._isChatFocused(chat);
|
||||
}
|
||||
|
||||
function openChatViaSidebarMessage(port, data, callback) {
|
||||
port.onmessage = function (e) {
|
||||
if (e.data.topic == "chatbox-opened")
|
||||
callback();
|
||||
}
|
||||
port.postMessage({topic: "test-chatbox-open", data: data});
|
||||
}
|
||||
|
||||
function openChatViaWorkerMessage(port, data, callback) {
|
||||
// sadly there is no message coming back to tell us when the chat has
|
||||
// been opened, so we wait until one appears.
|
||||
let chatbar = getChatBar();
|
||||
let numExpected = chatbar.childElementCount + 1;
|
||||
port.postMessage({topic: "test-worker-chat", data: data});
|
||||
waitForCondition(() => chatbar.childElementCount == numExpected,
|
||||
function() {
|
||||
// so the child has been added, but we don't know if it
|
||||
// has been intialized - re-request it and the callback
|
||||
// means it's done. Minimized, same as the worker.
|
||||
chatbar.openChat({
|
||||
origin: SocialSidebar.provider.origin,
|
||||
title: SocialSidebar.provider.name,
|
||||
url: data,
|
||||
mode: "minimized"
|
||||
}, function() { callback(); });
|
||||
},
|
||||
"No new chat appeared");
|
||||
}
|
||||
|
||||
|
||||
var isSidebarLoaded = false;
|
||||
|
||||
function startTestAndWaitForSidebar(callback) {
|
||||
let doneCallback;
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
function maybeCallback() {
|
||||
if (!doneCallback)
|
||||
callback(port);
|
||||
doneCallback = true;
|
||||
}
|
||||
port.onmessage = function(e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
// if sidebar loaded too fast, we need a backup ping
|
||||
case "got-isVisible-response":
|
||||
isSidebarLoaded = true;
|
||||
maybeCallback();
|
||||
break;
|
||||
case "test-init-done":
|
||||
if (isSidebarLoaded)
|
||||
maybeCallback();
|
||||
else
|
||||
port.postMessage({topic: "test-isVisible"});
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
}
|
||||
|
||||
var manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
|
||||
@ -103,58 +42,17 @@ function test() {
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
SocialSidebar.show();
|
||||
runSocialTests(tests, preSubTest, postSubTest, function () {
|
||||
finishcb();
|
||||
ensureBrowserTabClosed(tab).then(finishcb);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
registerCleanupFunction(function() {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var tests = {
|
||||
// In this test the worker asks the sidebar to open a chat. As that means
|
||||
// we aren't handling user-input we will not focus the chatbar.
|
||||
// Then we do it again - should still not be focused.
|
||||
// Then we perform a user-initiated request - it should get focus.
|
||||
testNoFocusWhenViaWorker: function(next) {
|
||||
let chatbar = getChatBar();
|
||||
startTestAndWaitForSidebar(function(port) {
|
||||
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
|
||||
ok(true, "got chatbox message");
|
||||
is(chatbar.childElementCount, 1, "exactly 1 chat open");
|
||||
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
ContentTask.spawn(browser, null, function* () {
|
||||
is(Services.focus.focusedWindow, content, "tab should still be focused");
|
||||
}).then(() => {
|
||||
// re-request the same chat via a message.
|
||||
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
|
||||
is(chatbar.childElementCount, 1, "still exactly 1 chat open");
|
||||
|
||||
ContentTask.spawn(browser, null, function* () {
|
||||
is(Services.focus.focusedWindow, content, "tab should still be focused");
|
||||
}).then(() => {
|
||||
// re-request the same chat via user event.
|
||||
openChatViaUser();
|
||||
waitForCondition(() => isChatFocused(chatbar.selectedChat), function() {
|
||||
is(chatbar.childElementCount, 1, "still exactly 1 chat open");
|
||||
is(chatbar.selectedChat, chatbar.firstElementChild,
|
||||
"chat should be selected");
|
||||
next();
|
||||
}, "chat should be focused");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// In this test we arrange for the sidebar to open the chat via a simulated
|
||||
// click. This should cause the new chat to be opened and focused.
|
||||
testFocusWhenViaUser: function(next) {
|
||||
startTestAndWaitForSidebar(function(port) {
|
||||
ensureFrameLoaded(document.getElementById("social-sidebar-browser")).then(() => {
|
||||
let chatbar = getChatBar();
|
||||
openChatViaUser();
|
||||
ok(chatbar.firstElementChild, "chat opened");
|
||||
|
@ -7,7 +7,6 @@ var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).So
|
||||
var manifest = { // used for testing install
|
||||
name: "provider test1",
|
||||
origin: "https://test1.example.com",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
markURL: "https://test1.example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
|
||||
markedIcon: "https://test1.example.com/browser/browser/base/content/test/social/unchecked.jpg",
|
||||
unmarkedIcon: "https://test1.example.com/browser/browser/base/content/test/social/checked.jpg",
|
||||
@ -18,9 +17,17 @@ var manifest = { // used for testing install
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addEventListener("OpenGraphData", function (aEvent) {
|
||||
sendAsyncMessage("sharedata", aEvent.detail);
|
||||
}, true, true);
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
@ -30,7 +37,6 @@ var tests = {
|
||||
testMarkMicroformats: function(next) {
|
||||
// emulates context menu action using target element, calling SocialMarks.markLink
|
||||
let provider = Social._getProviderFromOrigin(manifest.origin);
|
||||
let port = provider.getWorkerPort();
|
||||
let target, testTab;
|
||||
|
||||
// browser_share tests microformats on the full page, this is testing a
|
||||
@ -50,18 +56,13 @@ var tests = {
|
||||
}
|
||||
});
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
is(JSON.stringify(e.data.result), expecting, "microformats data ok");
|
||||
gBrowser.removeTab(testTab);
|
||||
port.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("sharedata", function handler(msg) {
|
||||
gBrowser.removeTab(testTab);
|
||||
is(msg.data, expecting, "microformats data ok");
|
||||
mm.removeMessageListener("sharedata", handler);
|
||||
next();
|
||||
});
|
||||
|
||||
let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
|
||||
addTab(url, function(tab) {
|
||||
|
@ -4,23 +4,45 @@
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addMessageListener("socialTest-CloseSelf", function(e) {
|
||||
content.close();
|
||||
});
|
||||
addEventListener("socialFrameShow", function(e) {
|
||||
sendAsyncMessage("social-visibility", "shown");
|
||||
}, false);
|
||||
addEventListener("socialFrameHide", function(e) {
|
||||
sendAsyncMessage("social-visibility", "hidden");
|
||||
}, false);
|
||||
|
||||
addMessageListener("socialTest-sendEvent", function(msg) {
|
||||
let data = msg.data;
|
||||
let evt = content.document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(data.name, true, true, JSON.stringify(data.data));
|
||||
content.document.documentElement.dispatchEvent(evt);
|
||||
});
|
||||
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
SocialSidebar.show();
|
||||
// disable transitions for the test
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
registerCleanupFunction(function () {
|
||||
panel.removeAttribute("animate");
|
||||
ensureFrameLoaded(document.getElementById("social-sidebar-browser")).then(() => {
|
||||
// disable transitions for the test
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
registerCleanupFunction(function () {
|
||||
panel.removeAttribute("animate");
|
||||
});
|
||||
panel.setAttribute("animate", "false");
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
panel.setAttribute("animate", "false");
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
}
|
||||
|
||||
@ -30,109 +52,61 @@ var tests = {
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
|
||||
});
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
port.postMessage({topic: "test-flyout-open"});
|
||||
break;
|
||||
case "got-flyout-visibility":
|
||||
if (e.data.result == "hidden") {
|
||||
ok(true, "flyout visibility is 'hidden'");
|
||||
is(panel.state, "closed", "panel really is closed");
|
||||
port.close();
|
||||
next();
|
||||
} else if (e.data.result == "shown") {
|
||||
ok(true, "flyout visibility is 'shown");
|
||||
port.postMessage({topic: "test-flyout-close"});
|
||||
}
|
||||
break;
|
||||
case "got-flyout-message":
|
||||
ok(e.data.result == "ok", "got flyout message");
|
||||
break;
|
||||
let sidebar = document.getElementById("social-sidebar-browser")
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("social-visibility", function handler(msg) {
|
||||
if (msg.data == "shown") {
|
||||
sidebar.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-close", data: {} });
|
||||
} else if (msg.data == "hidden") {
|
||||
mm.removeMessageListener("social-visibility", handler);
|
||||
next();
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
});
|
||||
sidebar.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
|
||||
},
|
||||
|
||||
testResizeFlyout: function(next) {
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
port.postMessage({topic: "test-flyout-open"});
|
||||
break;
|
||||
case "got-flyout-visibility":
|
||||
if (e.data.result != "shown")
|
||||
return;
|
||||
// The width of the flyout should be 400px initially
|
||||
let iframe = panel.firstChild;
|
||||
let body = iframe.contentDocument.body;
|
||||
let cs = iframe.contentWindow.getComputedStyle(body);
|
||||
|
||||
is(cs.width, "400px", "should be 400px wide");
|
||||
is(iframe.boxObject.width, 400, "iframe should now be 400px wide");
|
||||
is(cs.height, "400px", "should be 400px high");
|
||||
is(iframe.boxObject.height, 400, "iframe should now be 400px high");
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
|
||||
// The width of the flyout should be 400px initially
|
||||
let iframe = panel.firstChild;
|
||||
let body = iframe.contentDocument.body;
|
||||
let cs = iframe.contentWindow.getComputedStyle(body);
|
||||
|
||||
ensureEventFired(iframe.contentWindow, "resize").then(() => {
|
||||
cs = iframe.contentWindow.getComputedStyle(body);
|
||||
is(cs.width, "400px", "should be 400px wide");
|
||||
is(iframe.boxObject.width, 400, "iframe should now be 400px wide");
|
||||
is(cs.height, "400px", "should be 400px high");
|
||||
is(iframe.boxObject.height, 400, "iframe should now be 400px high");
|
||||
|
||||
is(cs.width, "500px", "should now be 500px wide");
|
||||
is(iframe.boxObject.width, 500, "iframe should now be 500px wide");
|
||||
is(cs.height, "500px", "should now be 500px high");
|
||||
is(iframe.boxObject.height, 500, "iframe should now be 500px high");
|
||||
panel.hidePopup();
|
||||
port.close();
|
||||
next();
|
||||
});
|
||||
SocialFlyout.dispatchPanelEvent("socialTest-MakeWider");
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
ensureEventFired(iframe.contentWindow, "resize").then(() => {
|
||||
cs = iframe.contentWindow.getComputedStyle(body);
|
||||
|
||||
is(cs.width, "500px", "should now be 500px wide");
|
||||
is(iframe.boxObject.width, 500, "iframe should now be 500px wide");
|
||||
is(cs.height, "500px", "should now be 500px high");
|
||||
is(iframe.boxObject.height, 500, "iframe should now be 500px high");
|
||||
ensureEventFired(panel, "popuphidden").then(next);
|
||||
panel.hidePopup();
|
||||
});
|
||||
SocialFlyout.dispatchPanelEvent("socialTest-MakeWider");
|
||||
});
|
||||
|
||||
let sidebar = document.getElementById("social-sidebar-browser");
|
||||
sidebar.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
|
||||
},
|
||||
|
||||
testCloseSelf: function(next) {
|
||||
// window.close is affected by the pref dom.allow_scripts_to_close_windows,
|
||||
// which defaults to false, but is set to true by the test harness.
|
||||
// so temporarily set it back.
|
||||
const ALLOW_SCRIPTS_TO_CLOSE_PREF = "dom.allow_scripts_to_close_windows";
|
||||
// note clearUserPref doesn't do what we expect, as the test harness itself
|
||||
// changes the pref value - so clearUserPref resets it to false rather than
|
||||
// the true setup by the test harness.
|
||||
let oldAllowScriptsToClose = Services.prefs.getBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF);
|
||||
Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, false);
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
port.postMessage({topic: "test-flyout-open"});
|
||||
break;
|
||||
case "got-flyout-visibility":
|
||||
if (e.data.result != "shown")
|
||||
return;
|
||||
let iframe = panel.firstChild;
|
||||
ensureEventFired(iframe.contentDocument, "SocialTest-DoneCloseSelf").then(() => {
|
||||
port.close();
|
||||
is(panel.state, "closed", "flyout should have closed itself");
|
||||
Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, oldAllowScriptsToClose);
|
||||
next();
|
||||
});
|
||||
is(panel.state, "open", "flyout should be open");
|
||||
SocialFlyout.dispatchPanelEvent("socialTest-CloseSelf");
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
|
||||
ensureEventFired(panel, "popuphidden").then(next);
|
||||
let mm = panel.firstChild.messageManager;
|
||||
mm.sendAsyncMessage("socialTest-CloseSelf", {});
|
||||
});
|
||||
let sidebar = document.getElementById("social-sidebar-browser");
|
||||
sidebar.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
|
||||
},
|
||||
|
||||
testCloseOnLinkTraversal: function(next) {
|
||||
@ -146,25 +120,14 @@ var tests = {
|
||||
}
|
||||
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
port.postMessage({topic: "test-flyout-open"});
|
||||
break;
|
||||
case "got-flyout-visibility":
|
||||
if (e.data.result == "shown") {
|
||||
// click on our test link
|
||||
is(panel.state, "open", "flyout should be open");
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
|
||||
let iframe = panel.firstChild;
|
||||
iframe.contentDocument.getElementById('traversal').click();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
|
||||
is(panel.state, "open", "flyout should be open");
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
|
||||
let iframe = panel.firstChild;
|
||||
iframe.contentDocument.getElementById('traversal').click();
|
||||
});
|
||||
let sidebar = document.getElementById("social-sidebar-browser");
|
||||
sidebar.messageManager.sendAsyncMessage("socialTest-sendEvent", { name: "test-flyout-open", data: {} });
|
||||
}
|
||||
}
|
||||
|
@ -9,59 +9,46 @@ function test() {
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addEventListener("socialFrameShow", function(e) {
|
||||
sendAsyncMessage("visibility", "shown");
|
||||
}, false);
|
||||
addEventListener("socialFrameHide", function(e) {
|
||||
sendAsyncMessage("visibility", "hidden");
|
||||
}, false);
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
});
|
||||
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
SocialSidebar.show();
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testSidebarMessage: function(next) {
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
port.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
testIsVisible: function(next) {
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-isVisible-response":
|
||||
is(e.data.result, true, "Sidebar should be visible by default");
|
||||
SocialSidebar.toggleSidebar();
|
||||
port.close();
|
||||
next();
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-isVisible"});
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("visibility", function handler(msg) {
|
||||
mm.removeMessageListener("visibility", handler);
|
||||
is(msg.data, "shown", "sidebar is visible");
|
||||
next();
|
||||
});
|
||||
SocialSidebar.show();
|
||||
},
|
||||
testIsNotVisible: function(next) {
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-isVisible-response":
|
||||
is(e.data.result, false, "Sidebar should be hidden");
|
||||
port.close();
|
||||
next();
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-isVisible"});
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.addMessageListener("visibility", function handler(msg) {
|
||||
mm.removeMessageListener("visibility", handler);
|
||||
is(msg.data, "hidden", "sidebar is hidden");
|
||||
next();
|
||||
});
|
||||
SocialSidebar.hide();
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ var SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).So
|
||||
var manifest2 = { // used for testing install
|
||||
name: "provider test1",
|
||||
origin: "https://test1.example.com",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
markURL: "https://test1.example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
|
||||
markedIcon: "https://test1.example.com/browser/browser/base/content/test/social/unchecked.jpg",
|
||||
unmarkedIcon: "https://test1.example.com/browser/browser/base/content/test/social/checked.jpg",
|
||||
@ -26,6 +25,21 @@ var manifest3 = { // used for testing install
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addEventListener("socialFrameShow", function(e) {
|
||||
sendAsyncMessage("visibility", "shown");
|
||||
}, false);
|
||||
addEventListener("socialFrameHide", function(e) {
|
||||
sendAsyncMessage("visibility", "hidden");
|
||||
}, false);
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
});
|
||||
|
||||
runSocialTests(tests, undefined, undefined, finish);
|
||||
}
|
||||
|
||||
@ -134,54 +148,37 @@ var tests = {
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
let btn = widget.forWindow(window).node;
|
||||
ok(btn, "got a mark button");
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "got a port");
|
||||
let ourTab;
|
||||
|
||||
ensureEventFired(btn.panel, "popupshown").then(() => {
|
||||
info("marks panel shown");
|
||||
let doc = btn.contentDocument;
|
||||
let unmarkBtn = doc.getElementById("unmark");
|
||||
ok(unmarkBtn, "testMarkPanel - got the panel unmark button");
|
||||
EventUtils.sendMouseEvent({type: "click"}, unmarkBtn, btn.contentWindow);
|
||||
});
|
||||
|
||||
ensureEventFired(btn.panel, "popuphidden").then(() => {
|
||||
ensureBrowserTabClosed(ourTab).then(() => {
|
||||
ok(btn.disabled, "button is disabled");
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// verify markbutton is disabled when there is no browser url
|
||||
ok(btn.disabled, "button is disabled");
|
||||
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||
addTab(activationURL, function(tab) {
|
||||
ourTab = tab;
|
||||
ok(!btn.disabled, "button is enabled");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
ok(true, "test-init-done received");
|
||||
ok(provider.profile.userName, "profile was set by test worker");
|
||||
// first click marks the page, second click opens the page. We have to
|
||||
// synthesize so the command event happens
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
// wait for the button to be marked, click to open panel
|
||||
is(btn.panel.state, "closed", "panel should not be visible yet");
|
||||
waitForCondition(() => btn.isMarked, function() {
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
}, "button is marked");
|
||||
break;
|
||||
case "got-social-panel-visibility":
|
||||
ok(true, "got the panel message " + e.data.result);
|
||||
if (e.data.result == "shown") {
|
||||
// unmark the page via the button in the page
|
||||
ensureFrameLoaded(btn.content).then(() => {
|
||||
let doc = btn.contentDocument;
|
||||
let unmarkBtn = doc.getElementById("unmark");
|
||||
ok(unmarkBtn, "testMarkPanel - got the panel unmark button");
|
||||
EventUtils.sendMouseEvent({type: "click"}, unmarkBtn, btn.contentWindow);
|
||||
});
|
||||
} else {
|
||||
// page should no longer be marked
|
||||
port.close();
|
||||
waitForCondition(() => !btn.isMarked, function() {
|
||||
// cleanup after the page has been unmarked
|
||||
ensureBrowserTabClosed(tab).then(() => {
|
||||
ok(btn.disabled, "button is disabled");
|
||||
next();
|
||||
});
|
||||
}, "button unmarked");
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-init"});
|
||||
// first click marks the page, second click opens the page. We have to
|
||||
// synthesize so the command event happens
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
// wait for the button to be marked, click to open panel
|
||||
is(btn.panel.state, "closed", "panel should not be visible yet");
|
||||
waitForCondition(() => btn.isMarked, function() {
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
}, "button is marked");
|
||||
});
|
||||
},
|
||||
|
||||
@ -218,67 +215,6 @@ var tests = {
|
||||
});
|
||||
},
|
||||
|
||||
testMarkPanelLoggedOut: function(next) {
|
||||
// click on panel to open and wait for visibility
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
ok(provider.enabled, "provider is enabled");
|
||||
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
let btn = widget.forWindow(window).node;
|
||||
ok(btn, "got a mark button");
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "got a port");
|
||||
|
||||
// verify markbutton is disabled when there is no browser url
|
||||
ok(btn.disabled, "button is disabled");
|
||||
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||
addTab(activationURL, function(tab) {
|
||||
ok(!btn.disabled, "button is enabled");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
ok(true, "test-init-done received");
|
||||
ok(provider.profile.userName, "profile was set by test worker");
|
||||
port.postMessage({topic: "test-logout"});
|
||||
waitForCondition(() => !provider.profile.userName,
|
||||
function() {
|
||||
// when the provider has not indicated to us that a user is
|
||||
// logged in, the first click opens the page.
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
},
|
||||
"profile was unset by test worker");
|
||||
break;
|
||||
case "got-social-panel-visibility":
|
||||
ok(true, "got the panel message " + e.data.result);
|
||||
if (e.data.result == "shown") {
|
||||
// our test marks the page during the load event (see
|
||||
// social_mark.html) regardless of login state, unmark the page
|
||||
// via the button in the page
|
||||
ensureFrameLoaded(btn.content).then(() => {
|
||||
let doc = btn.contentDocument;
|
||||
let unmarkBtn = doc.getElementById("unmark");
|
||||
ok(unmarkBtn, "testMarkPanelLoggedOut - got the panel unmark button");
|
||||
EventUtils.sendMouseEvent({type: "click"}, unmarkBtn, btn.contentWindow);
|
||||
});
|
||||
} else {
|
||||
// page should no longer be marked
|
||||
port.close();
|
||||
waitForCondition(() => !btn.isMarked, function() {
|
||||
// cleanup after the page has been unmarked
|
||||
ensureBrowserTabClosed(tab).then(() => {
|
||||
ok(btn.disabled, "button is disabled");
|
||||
next();
|
||||
});
|
||||
}, "button unmarked");
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-init"});
|
||||
});
|
||||
},
|
||||
|
||||
testButtonOnDisable: function(next) {
|
||||
// enable the provider now
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
|
@ -17,20 +17,19 @@ var gProviders = [
|
||||
name: "provider 1",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider 2",
|
||||
origin: "https://test2.example.com",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test2.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
}
|
||||
];
|
||||
|
||||
var tests = {
|
||||
testProviderSwitch: function(next) {
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
let menu = document.getElementById("social-statusarea-popup");
|
||||
let button = document.getElementById("social-sidebar-button");
|
||||
function checkProviderMenu(selectedProvider) {
|
||||
@ -43,36 +42,32 @@ var tests = {
|
||||
}
|
||||
|
||||
// the menu is not populated until onpopupshowing, so wait for popupshown
|
||||
function theTest() {
|
||||
menu.removeEventListener("popupshown", theTest, true);
|
||||
ensureEventFired(menu, "popupshown").then(()=>{
|
||||
menu.hidePopup(); // doesn't need visibility
|
||||
// first provider should already be visible in the sidebar
|
||||
is(Social.providers[0].origin, SocialSidebar.provider.origin, "selected provider in sidebar");
|
||||
checkProviderMenu(Social.providers[0]);
|
||||
|
||||
// Now activate "provider 2"
|
||||
onSidebarLoad(function() {
|
||||
ensureEventFired(sbrowser, "load").then(()=>{
|
||||
checkUIStateMatchesProvider(Social.providers[1]);
|
||||
|
||||
onSidebarLoad(function() {
|
||||
ensureEventFired(sbrowser, "load").then(()=>{
|
||||
checkUIStateMatchesProvider(Social.providers[0]);
|
||||
next();
|
||||
});
|
||||
|
||||
// show the menu again so the menu is updated with the correct commands
|
||||
function doClick() {
|
||||
ensureEventFired(menu, "popupshown").then(()=>{
|
||||
// click on the provider menuitem to switch providers
|
||||
let el = menu.getElementsByAttribute("origin", Social.providers[0].origin);
|
||||
is(el.length, 1, "selected provider menu item exists");
|
||||
EventUtils.synthesizeMouseAtCenter(el[0], {});
|
||||
}
|
||||
menu.addEventListener("popupshown", doClick, true);
|
||||
});
|
||||
EventUtils.synthesizeMouseAtCenter(button, {});
|
||||
|
||||
});
|
||||
SocialSidebar.provider = Social.providers[1];
|
||||
};
|
||||
menu.addEventListener("popupshown", theTest, true);
|
||||
});
|
||||
EventUtils.synthesizeMouseAtCenter(button, {});
|
||||
}
|
||||
}
|
||||
@ -81,16 +76,3 @@ function checkUIStateMatchesProvider(provider) {
|
||||
// Sidebar
|
||||
is(document.getElementById("social-sidebar-browser").getAttribute("src"), provider.sidebarURL, "side bar URL is set");
|
||||
}
|
||||
|
||||
function onSidebarLoad(callback) {
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
sbrowser.addEventListener("load", function load(evt) {
|
||||
if (evt.target != sbrowser.contentDocument) {
|
||||
return;
|
||||
}
|
||||
sbrowser.removeEventListener("load", load, true);
|
||||
// give the load a chance to finish before pulling the rug (ie. calling
|
||||
// next)
|
||||
executeSoon(callback);
|
||||
}, true);
|
||||
}
|
||||
|
@ -1,70 +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/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
runSocialTestWithProvider(gProviders, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function() {
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var gProviders = [
|
||||
{
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider 2",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
}
|
||||
];
|
||||
|
||||
var tests = {
|
||||
testWorkersAlive: function(next) {
|
||||
// verify we can get a message from all providers that are enabled
|
||||
let messageReceived = 0;
|
||||
function oneWorkerTest(provider) {
|
||||
let port = provider.getWorkerPort();
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
ok(true, "got message from provider " + provider.name);
|
||||
port.close();
|
||||
messageReceived++;
|
||||
break;
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-init"});
|
||||
}
|
||||
|
||||
for (let p of Social.providers) {
|
||||
oneWorkerTest(p);
|
||||
}
|
||||
|
||||
waitForCondition(() => messageReceived == Social.providers.length,
|
||||
next, "received messages from all workers",
|
||||
/* increase timeout because shutting down a child process is slow */ 60);
|
||||
},
|
||||
|
||||
testMultipleWorkerEnabling: function(next) {
|
||||
// test that all workers are enabled when we allow multiple workers
|
||||
for (let p of Social.providers) {
|
||||
ok(p.enabled, "provider enabled");
|
||||
let port = p.getWorkerPort();
|
||||
ok(port, "worker enabled");
|
||||
port.close();
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
@ -1,100 +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/. */
|
||||
|
||||
function openTab(win, url, callback) {
|
||||
let newTab = win.gBrowser.addTab(url);
|
||||
let tabBrowser = win.gBrowser.getBrowserForTab(newTab);
|
||||
tabBrowser.addEventListener("load", function tabLoadListener() {
|
||||
tabBrowser.removeEventListener("load", tabLoadListener, true);
|
||||
win.gBrowser.selectedTab = newTab;
|
||||
callback(newTab);
|
||||
}, true)
|
||||
}
|
||||
|
||||
// Tests for per-window private browsing.
|
||||
function openPBWindow(callback) {
|
||||
let w = OpenBrowserWindow({private: true});
|
||||
w.addEventListener("load", function loadListener() {
|
||||
w.removeEventListener("load", loadListener);
|
||||
openTab(w, "http://example.com", function() {
|
||||
callback(w);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function postAndReceive(port, postTopic, receiveTopic, callback) {
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == receiveTopic)
|
||||
callback();
|
||||
}
|
||||
port.postMessage({topic: postTopic});
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
statusURL: "https://example.com/browser/browser/base/content/test/social/social_panel.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
markURL: "https://example.com/browser/browser/base/content/test/social/social_mark.html?url=%{url}",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
openTab(window, "http://example.com", function(newTab) {
|
||||
runSocialTests(tests, undefined, undefined, function() {
|
||||
window.gBrowser.removeTab(newTab);
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testPrivateBrowsing: function(next) {
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
postAndReceive(port, "test-init", "test-init-done", function() {
|
||||
// social features should all be enabled in the existing window.
|
||||
info("checking main window ui");
|
||||
ok(window.SocialUI.enabled, "social is enabled in normal window");
|
||||
checkSocialUI(window);
|
||||
// open a new private-window
|
||||
openPBWindow(function(pbwin) {
|
||||
// The provider should remain alive.
|
||||
postAndReceive(port, "ping", "pong", function() {
|
||||
// the new window should have no social features at all.
|
||||
info("checking private window ui");
|
||||
ok(!pbwin.SocialUI.enabled, "social is disabled in a PB window");
|
||||
checkSocialUI(pbwin);
|
||||
|
||||
// but they should all remain enabled in the initial window
|
||||
info("checking main window ui");
|
||||
ok(window.SocialUI.enabled, "social is still enabled in normal window");
|
||||
checkSocialUI(window);
|
||||
|
||||
// Check that the status button is disabled on the private
|
||||
// browsing window and not on the normal window.
|
||||
let id = SocialStatus._toolbarHelper.idFromOrigin("https://example.com");
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
ok(widget.forWindow(pbwin).node.disabled, "status button disabled on private window");
|
||||
ok(!widget.forWindow(window).node.disabled, "status button enabled on normal window");
|
||||
|
||||
// Check that the mark button is disabled on the private
|
||||
// browsing window and not on the normal window.
|
||||
id = SocialMarks._toolbarHelper.idFromOrigin("https://example.com");
|
||||
widget = CustomizableUI.getWidget(id);
|
||||
ok(widget.forWindow(pbwin).node.disabled, "mark button disabled on private window");
|
||||
ok(!widget.forWindow(window).node.disabled, "mark button enabled on normal window");
|
||||
|
||||
// that's all folks...
|
||||
pbwin.close();
|
||||
next();
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
@ -8,7 +8,6 @@ var manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
|
||||
@ -24,7 +23,6 @@ function test() {
|
||||
function doTest() {
|
||||
ok(SocialSidebar.canShow, "social sidebar should be able to be shown");
|
||||
ok(!SocialSidebar.opened, "social sidebar should not be open by default");
|
||||
SocialSidebar.show();
|
||||
|
||||
let command = document.getElementById("Social:ToggleSidebar");
|
||||
let sidebar = document.getElementById("social-sidebar-box");
|
||||
@ -57,17 +55,14 @@ function doTest() {
|
||||
|
||||
// First check the the sidebar is initially visible, and loaded
|
||||
ok(!command.hidden, "toggle command should be visible");
|
||||
checkShown(true);
|
||||
|
||||
browser.addEventListener("socialFrameHide", function sidebarhide() {
|
||||
browser.removeEventListener("socialFrameHide", sidebarhide);
|
||||
ensureEventFired(browser, "socialFrameShow").then(function sidebarhide() {
|
||||
|
||||
checkShown(false);
|
||||
checkShown(true);
|
||||
|
||||
browser.addEventListener("socialFrameShow", function sidebarshow() {
|
||||
browser.removeEventListener("socialFrameShow", sidebarshow);
|
||||
ensureEventFired(browser, "socialFrameHide").then(function sidebarshow() {
|
||||
|
||||
checkShown(true);
|
||||
checkShown(false);
|
||||
|
||||
// disable social.
|
||||
SocialService.disableProvider(SocialSidebar.provider.origin, function() {
|
||||
@ -83,17 +78,5 @@ function doTest() {
|
||||
info("Toggling sidebar back on");
|
||||
SocialSidebar.toggleSidebar();
|
||||
});
|
||||
|
||||
// use port messaging to ensure that the sidebar is both loaded and
|
||||
// ready before we run other tests
|
||||
let port = SocialSidebar.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
ok(true, "sidebar is loaded and ready");
|
||||
SocialSidebar.toggleSidebar();
|
||||
}
|
||||
};
|
||||
SocialSidebar.show();
|
||||
}
|
||||
|
@ -8,13 +8,11 @@ var manifest = { // builtin provider
|
||||
name: "provider example.com",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
var manifest2 = { // used for testing install
|
||||
name: "provider test1",
|
||||
origin: "https://test1.example.com",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
statusURL: "https://test1.example.com/browser/browser/base/content/test/social/social_panel.html",
|
||||
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
|
||||
version: "1.0"
|
||||
@ -40,6 +38,27 @@ function openWindowAndWaitForInit(callback) {
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let frameScript = "data:,(" + function frame_script() {
|
||||
addEventListener("socialFrameShow", function(e) {
|
||||
sendAsyncMessage("visibility", "shown");
|
||||
}, false);
|
||||
addEventListener("socialFrameHide", function(e) {
|
||||
sendAsyncMessage("visibility", "hidden");
|
||||
}, false);
|
||||
addMessageListener("socialTest-sendEvent", function(msg) {
|
||||
let data = msg.data;
|
||||
let evt = content.document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(data.name, true, true, JSON.stringify(data.data));
|
||||
content.document.documentElement.dispatchEvent(evt);
|
||||
});
|
||||
}.toString() + ")();";
|
||||
let mm = getGroupMessageManager("social");
|
||||
mm.loadFrameScript(frameScript, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mm.removeDelayedFrameScript(frameScript);
|
||||
});
|
||||
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
Services.prefs.clearUserPref("social.remote-install.enabled");
|
||||
@ -123,44 +142,31 @@ var tests = {
|
||||
counter: 1
|
||||
};
|
||||
|
||||
// Disable the transition
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.setAttribute("animate", "false");
|
||||
|
||||
// click on panel to open and wait for visibility
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
|
||||
let widget = CustomizableUI.getWidget(id);
|
||||
let btn = widget.forWindow(window).node;
|
||||
ok(btn, "got a status button");
|
||||
let port = provider.getWorkerPort();
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
ok(true, "test-init-done received");
|
||||
ok(provider.profile.userName, "profile was set by test worker");
|
||||
btn.click();
|
||||
break;
|
||||
case "got-social-panel-visibility":
|
||||
ok(true, "got the panel message " + e.data.result);
|
||||
if (e.data.result == "shown") {
|
||||
panel.hidePopup();
|
||||
panel.removeAttribute("animate");
|
||||
} else {
|
||||
port.postMessage({topic: "test-ambient-notification", data: icon});
|
||||
port.close();
|
||||
waitForCondition(function() { return btn.getAttribute("badge"); },
|
||||
function() {
|
||||
is(btn.style.listStyleImage, "url(\"" + icon.iconURL + "\")", "notification icon updated");
|
||||
next();
|
||||
}, "button updated by notification");
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-init"});
|
||||
// Disable the transition
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.setAttribute("animate", "false");
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
ensureFrameLoaded(panel.firstChild).then(() => {
|
||||
let mm = panel.firstChild.messageManager;
|
||||
mm.sendAsyncMessage("socialTest-sendEvent", { name: "Social:Notification", data: icon });
|
||||
waitForCondition(function() { return btn.getAttribute("badge"); },
|
||||
function() {
|
||||
is(btn.style.listStyleImage, "url(\"" + icon.iconURL + "\")", "notification icon updated");
|
||||
panel.hidePopup();
|
||||
}, "button updated by notification");
|
||||
});
|
||||
});
|
||||
ensureEventFired(panel, "popuphidden").then(() => {
|
||||
panel.removeAttribute("animate");
|
||||
next();
|
||||
});
|
||||
btn.click(); // open the panel
|
||||
},
|
||||
|
||||
testPanelOffline: function(next) {
|
||||
@ -173,8 +179,6 @@ var tests = {
|
||||
ok(btn, "got a status button");
|
||||
let frameId = btn.getAttribute("notificationFrameId");
|
||||
let frame = document.getElementById(frameId);
|
||||
let port = provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
|
||||
goOffline().then(function() {
|
||||
info("testing offline error page");
|
||||
@ -183,8 +187,16 @@ var tests = {
|
||||
ensureEventFired(panel, "popupshown").then(() => {
|
||||
ensureFrameLoaded(frame).then(() => {
|
||||
is(frame.contentDocument.documentURI.indexOf("about:socialerror?mode=tryAgainOnly"), 0, "social error page is showing "+frame.contentDocument.documentURI);
|
||||
panel.hidePopup();
|
||||
goOnline().then(next);
|
||||
// We got our error page, reset to avoid test leak.
|
||||
ensureEventFired(frame, "load").then(() => {
|
||||
is(frame.contentDocument.documentURI, "about:blank", "closing error panel");
|
||||
ensureEventFired(panel, "popuphidden").then(next);
|
||||
panel.hidePopup();
|
||||
});
|
||||
goOnline().then(() => {
|
||||
info("resetting error panel");
|
||||
frame.setAttribute("src", "about:blank");
|
||||
});
|
||||
});
|
||||
});
|
||||
// reload after going offline, wait for unload to open panel
|
||||
|
@ -55,13 +55,11 @@ var manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
|
||||
};
|
||||
var manifest2 = { // used for testing install
|
||||
name: "provider test1",
|
||||
origin: "https://test1.example.com",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
|
||||
};
|
||||
|
@ -1,157 +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/. */
|
||||
|
||||
// This tests our recovery if a child content process hosting providers
|
||||
// crashes.
|
||||
|
||||
// A content script we inject into one of our browsers
|
||||
const TEST_CONTENT_HELPER = "chrome://mochitests/content/browser/browser/base/content/test/social/social_crash_content_helper.js";
|
||||
|
||||
var {getFrameWorkerHandle} = Cu.import("resource://gre/modules/FrameWorker.jsm", {});
|
||||
var {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// We need to ensure all our workers are in the same content process.
|
||||
Services.prefs.setIntPref("dom.ipc.processCount", 1);
|
||||
|
||||
// This test generates many uncaught promises that should not cause failures.
|
||||
Promise.Debugging.clearUncaughtErrorObservers();
|
||||
|
||||
runSocialTestWithProvider(gProviders, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function() {
|
||||
Services.prefs.clearUserPref("dom.ipc.processCount");
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var gProviders = [
|
||||
{
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider 2",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
}
|
||||
];
|
||||
|
||||
var tests = {
|
||||
testCrash: function(next) {
|
||||
// open the sidebar, then crash the child.
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
onSidebarLoad(function() {
|
||||
// get the browser element for our provider.
|
||||
let fw = getFrameWorkerHandle(gProviders[0].workerURL);
|
||||
fw.port.close();
|
||||
fw._worker.browserPromise.then(browser => {
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(TEST_CONTENT_HELPER, false);
|
||||
// add an observer for the crash - after it sees the crash we attempt
|
||||
// a reload.
|
||||
let observer = new crashObserver(function() {
|
||||
info("Saw the process crash.")
|
||||
Services.obs.removeObserver(observer, 'ipc:content-shutdown');
|
||||
// Add another sidebar load listener - it should be the error page.
|
||||
onSidebarLoad(function() {
|
||||
ok(sbrowser.contentDocument.location.href.indexOf("about:socialerror?mode=workerFailure")==0, "is on social error page");
|
||||
// after reloading, the sidebar should reload
|
||||
onSidebarLoad(function() {
|
||||
// now ping both workers - they should both be alive.
|
||||
ensureWorkerLoaded(gProviders[0], function() {
|
||||
ensureWorkerLoaded(gProviders[1], function() {
|
||||
// and we are done!
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
// click the try-again button.
|
||||
sbrowser.contentDocument.getElementById("btnTryAgain").click();
|
||||
});
|
||||
});
|
||||
Services.obs.addObserver(observer, 'ipc:content-shutdown', false);
|
||||
// and cause the crash.
|
||||
mm.sendAsyncMessage("social-test:crash");
|
||||
});
|
||||
})
|
||||
SocialSidebar.show();
|
||||
},
|
||||
}
|
||||
|
||||
function onSidebarLoad(callback) {
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
sbrowser.addEventListener("load", function load() {
|
||||
sbrowser.removeEventListener("load", load, true);
|
||||
callback();
|
||||
}, true);
|
||||
}
|
||||
|
||||
function ensureWorkerLoaded(manifest, callback) {
|
||||
let fw = getFrameWorkerHandle(manifest.workerURL);
|
||||
// once the worker responds to a ping we know it must be up.
|
||||
let port = fw.port;
|
||||
port.onmessage = function(msg) {
|
||||
if (msg.data.topic == "pong") {
|
||||
port.close();
|
||||
callback();
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "ping"})
|
||||
}
|
||||
|
||||
// More duplicated code from browser_thumbnails_brackground_crash.
|
||||
// Bug 915518 exists to unify these.
|
||||
|
||||
// This observer is needed so we can clean up all evidence of the crash so
|
||||
// the testrunner thinks things are peachy.
|
||||
var crashObserver = function(callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
crashObserver.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
|
||||
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
|
||||
'Subject implements nsIPropertyBag2.');
|
||||
// we might see this called as the process terminates due to previous tests.
|
||||
// We are only looking for "abnormal" exits...
|
||||
if (!subject.hasKey("abnormal")) {
|
||||
info("This is a normal termination and isn't the one we are looking for...");
|
||||
return;
|
||||
}
|
||||
|
||||
var dumpID;
|
||||
if ('nsICrashReporter' in Components.interfaces) {
|
||||
dumpID = subject.getPropertyAsAString('dumpID');
|
||||
ok(dumpID, "dumpID is present and not an empty string");
|
||||
}
|
||||
|
||||
if (dumpID) {
|
||||
var minidumpDirectory = getMinidumpDirectory();
|
||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||
}
|
||||
this.callback();
|
||||
}
|
||||
}
|
||||
|
||||
function getMinidumpDirectory() {
|
||||
var dir = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile);
|
||||
dir.append("minidumps");
|
||||
return dir;
|
||||
}
|
||||
function removeFile(directory, filename) {
|
||||
var file = directory.clone();
|
||||
file.append(filename);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
}
|
||||
}
|
@ -89,7 +89,7 @@ function runSocialTestWithProvider(manifest, callback, finishcallback) {
|
||||
SessionStore.setWindowValue(window, "socialSidebar", "");
|
||||
for (let i = 0; i < manifests.length; i++) {
|
||||
let m = manifests[i];
|
||||
for (let what of ['sidebarURL', 'workerURL', 'iconURL', 'shareURL', 'markURL']) {
|
||||
for (let what of ['sidebarURL', 'iconURL', 'shareURL', 'markURL']) {
|
||||
if (m[what]) {
|
||||
yield promiseSocialUrlNotRemembered(m[what]);
|
||||
}
|
||||
@ -194,8 +194,7 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
|
||||
return;
|
||||
}
|
||||
let [name, func] = result.value;
|
||||
// We run on a timeout as the frameworker also makes use of timeouts, so
|
||||
// this helps keep the debug messages sane.
|
||||
// We run on a timeout to help keep the debug messages sane.
|
||||
executeSoon(function() {
|
||||
function cleanupAndRunNextTest() {
|
||||
info("sub-test " + name + " complete");
|
||||
@ -441,9 +440,6 @@ function get3ChatsForCollapsing(mode, cb) {
|
||||
// ensure a second can be created fully visible but a third can not - then
|
||||
// create the other 2. first will will be collapsed, second fully visible
|
||||
// and the third also visible and the "selected" one.
|
||||
// To make our life easier we don't go via the worker and ports so we get
|
||||
// more control over creation *and* to make the code much simpler. We
|
||||
// assume the worker/port stuff is individually tested above.
|
||||
let chatbar = getChatBar();
|
||||
let chatWidth = undefined;
|
||||
let num = 0;
|
||||
@ -508,7 +504,7 @@ function makeChat(mode, uniqueid, cb) {
|
||||
chatbox.content.messageManager.sendAsyncMessage("Social:SetDocumentTitle", {
|
||||
title: uniqueid
|
||||
});
|
||||
cb();
|
||||
cb(chatbox);
|
||||
});
|
||||
}
|
||||
|
||||
@ -630,15 +626,15 @@ function getPopupWidth() {
|
||||
return popup.parentNode.getBoundingClientRect().width + margins;
|
||||
}
|
||||
|
||||
function promiseCloseChat(chat) {
|
||||
function promiseNodeRemoved(aNode) {
|
||||
let deferred = Promise.defer();
|
||||
let parent = chat.parentNode;
|
||||
let parent = aNode.parentNode;
|
||||
|
||||
let observer = new MutationObserver(function onMutatations(mutations) {
|
||||
for (let mutation of mutations) {
|
||||
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
||||
let node = mutation.removedNodes.item(i);
|
||||
if (node != chat) {
|
||||
if (node != aNode) {
|
||||
continue;
|
||||
}
|
||||
observer.disconnect();
|
||||
@ -647,10 +643,15 @@ function promiseCloseChat(chat) {
|
||||
}
|
||||
});
|
||||
observer.observe(parent, {childList: true});
|
||||
chat.close();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseCloseChat(chat) {
|
||||
let promise = promiseNodeRemoved(chat);
|
||||
chat.close();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function closeAllChats() {
|
||||
let chatbar = getChatBar();
|
||||
while (chatbar.selectedChat) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
<img class="photo" src="https://example.com/someimage.jpg" />
|
||||
<p class="description">The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.</p>
|
||||
<a class="url" href="https://example.com/">More info about the Raspberry Pi</a>
|
||||
<p class="price">£29.95</p>
|
||||
<p class="price">29.95</p>
|
||||
<p class="review hreview"><span id="test-review" class="rating">4.5</span> out of 5</p>
|
||||
<p>Categories:
|
||||
<a rel="tag" href="https://example.com/wiki/computer" class="category">Computer</a>,
|
||||
|
@ -2,11 +2,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
var shareData;
|
||||
addEventListener("OpenGraphData", function(e) {
|
||||
shareData = JSON.parse(e.detail);
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "share-data-message", result: shareData});
|
||||
// frame scripts handle test data
|
||||
// share windows self-close
|
||||
history.back(); // bug 1042991, ensure history is available
|
||||
window.close();
|
||||
|
@ -15,7 +15,6 @@ var data = {
|
||||
"iconURL": "chrome://branding/content/icon16.png",
|
||||
"icon32URL": "chrome://branding/content/favicon32.png",
|
||||
"icon64URL": "chrome://branding/content/icon64.png",
|
||||
"workerURL": "/browser/browser/base/content/test/social/social_worker.js",
|
||||
"shareURL": "/browser/browser/base/content/test/social/share.html"
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ var data = {
|
||||
|
||||
// at least one of these must be defined
|
||||
"sidebarURL": "/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
"workerURL": "/browser/browser/base/content/test/social/social_worker.js",
|
||||
"statusURL": "/browser/browser/base/content/test/social/social_panel.html",
|
||||
"postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
|
||||
|
||||
|
@ -1,26 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-message", result: "ok"});
|
||||
}
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-visibility", result: "hidden"});
|
||||
}, false);
|
||||
window.addEventListener("socialTest-CloseSelf", function(e) {
|
||||
window.close();
|
||||
}, false);
|
||||
</script>
|
||||
<title>test chat window</title>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<body>
|
||||
<p>This is a test social chat window.</p>
|
||||
<!-- a couple of input fields to help with focus testing -->
|
||||
<input id="input1"/>
|
||||
|
@ -2,18 +2,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "flyout-message", result: "ok"});
|
||||
}
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "flyout-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "flyout-visibility", result: "hidden"});
|
||||
}, false);
|
||||
window.addEventListener("socialTest-MakeWider", function(e) {
|
||||
document.body.setAttribute("style", "width: 500px; height: 500px; margin: 0; overflow: hidden;");
|
||||
document.body.offsetWidth; // force a layout flush
|
||||
@ -29,7 +17,7 @@
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body style="width: 400px; height: 400px; margin: 0; overflow: hidden;" onload="pingWorker();">
|
||||
<body style="width: 400px; height: 400px; margin: 0; overflow: hidden;">
|
||||
<p>This is a test social flyout panel.</p>
|
||||
<a id="traversal" href="https://test.example.com">test link</a>
|
||||
</body>
|
||||
|
@ -4,14 +4,6 @@
|
||||
<link id="siteicon" rel="icon" href="./icon.png"/>
|
||||
<title>Demo Mark Window</title>
|
||||
<script type="text/javascript">
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "hidden"});
|
||||
}, false);
|
||||
|
||||
function updateTextNode(parent, text) {
|
||||
var textNode = parent.childNodes[0];
|
||||
@ -34,8 +26,6 @@
|
||||
shareData = JSON.parse(e.detail);
|
||||
updateTextNode(document.getElementById("shared"), shareData.url);
|
||||
socialMarkUpdate(true);
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "share-data-message", result: shareData});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
@ -1,24 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "panel-message",
|
||||
result: "ok",
|
||||
location: window.location.href});
|
||||
}
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "hidden"});
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<body>
|
||||
<p>This is a test social panel.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,40 +2,15 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
var testwindow;
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.onmessage = function(e) {
|
||||
var topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-flyout-open":
|
||||
navigator.mozSocial.openPanel("social_flyout.html");
|
||||
break;
|
||||
case "test-flyout-close":
|
||||
navigator.mozSocial.closePanel();
|
||||
break;
|
||||
case "test-chatbox-open":
|
||||
var url = "social_chat.html";
|
||||
var data = e.data.data;
|
||||
if (data && data.id) {
|
||||
url = url + "?id="+data.id;
|
||||
}
|
||||
navigator.mozSocial.openChatWindow(url, function(success) {
|
||||
port.postMessage({topic: "chatbox-opened",
|
||||
result: success ? "ok" : "failed"});
|
||||
});
|
||||
break;
|
||||
case "test-isVisible":
|
||||
port.postMessage({topic: "test-isVisible-response",
|
||||
result: navigator.mozSocial.isVisible});
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "sidebar-message", result: "ok"});
|
||||
}
|
||||
addEventListener("test-flyout-open", function(e) {
|
||||
navigator.mozSocial.openPanel("social_flyout.html");
|
||||
}, false);
|
||||
addEventListener("test-flyout-close", function(e) {
|
||||
navigator.mozSocial.closePanel();
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<body>
|
||||
<p>This is a test social sidebar.</p>
|
||||
<button id="chat-opener" onclick="navigator.mozSocial.openChatWindow('./social_chat.html');"/>
|
||||
</body>
|
||||
|
@ -1,17 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "service-window-message",
|
||||
location: window.location.href,
|
||||
result: "ok"
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social service window.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,137 +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/. */
|
||||
|
||||
var testPort, sidebarPort, apiPort, updatingManifest=false;
|
||||
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function onMessage(event) {
|
||||
let topic = event.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init":
|
||||
testPort = port;
|
||||
port.postMessage({topic: "test-init-done"});
|
||||
break;
|
||||
case "ping":
|
||||
port.postMessage({topic: "pong"});
|
||||
break;
|
||||
case "test-logout":
|
||||
apiPort.postMessage({topic: "social.user-profile", data: {}});
|
||||
break;
|
||||
case "sidebar-message":
|
||||
sidebarPort = port;
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-sidebar-message"});
|
||||
break;
|
||||
case "service-window-message":
|
||||
testPort.postMessage({topic:"got-service-window-message",
|
||||
location: event.data.location});
|
||||
break;
|
||||
case "service-window-closed-message":
|
||||
testPort.postMessage({topic:"got-service-window-closed-message"});
|
||||
break;
|
||||
case "test-service-window":
|
||||
sidebarPort.postMessage({topic:"test-service-window"});
|
||||
break;
|
||||
case "test-service-window-twice":
|
||||
sidebarPort.postMessage({topic:"test-service-window-twice"});
|
||||
break;
|
||||
case "test-service-window-twice-result":
|
||||
testPort.postMessage({topic: "test-service-window-twice-result", result: event.data.result })
|
||||
break;
|
||||
case "test-close-service-window":
|
||||
sidebarPort.postMessage({topic:"test-close-service-window"});
|
||||
break;
|
||||
case "panel-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-panel-message",
|
||||
location: event.data.location
|
||||
});
|
||||
break;
|
||||
case "status-panel-visibility":
|
||||
testPort.postMessage({topic:"got-social-panel-visibility", result: event.data.result });
|
||||
break;
|
||||
case "test-chatbox-open":
|
||||
sidebarPort.postMessage(event.data);
|
||||
break;
|
||||
case "chatbox-opened":
|
||||
testPort.postMessage(event.data);
|
||||
break;
|
||||
case "chatbox-message":
|
||||
testPort.postMessage({topic:"got-chatbox-message", result: event.data.result});
|
||||
break;
|
||||
case "chatbox-visibility":
|
||||
testPort.postMessage({topic:"got-chatbox-visibility", result: event.data.result});
|
||||
break;
|
||||
case "test-flyout-open":
|
||||
sidebarPort.postMessage({topic:"test-flyout-open"});
|
||||
break;
|
||||
case "flyout-message":
|
||||
testPort.postMessage({topic:"got-flyout-message", result: event.data.result});
|
||||
break;
|
||||
case "flyout-visibility":
|
||||
testPort.postMessage({topic:"got-flyout-visibility", result: event.data.result});
|
||||
break;
|
||||
case "test-flyout-close":
|
||||
sidebarPort.postMessage({topic:"test-flyout-close"});
|
||||
break;
|
||||
case "test-worker-chat":
|
||||
apiPort.postMessage({topic: "social.request-chat", data: event.data.data });
|
||||
break;
|
||||
case "social.initialize":
|
||||
// This is the workerAPI port, respond and set up a notification icon.
|
||||
// For multiprovider tests, we support acting like different providers
|
||||
// based on the domain we load from.
|
||||
apiPort = port;
|
||||
// purposely fall through and set the profile on initialization
|
||||
case "test-set-profile":
|
||||
let profile;
|
||||
if (location.href.indexOf("https://test1.example.com") == 0) {
|
||||
profile = {
|
||||
portrait: "https://test1.example.com/portrait.jpg",
|
||||
userName: "tester",
|
||||
displayName: "Test1 User",
|
||||
};
|
||||
} else {
|
||||
profile = {
|
||||
portrait: "https://example.com/portrait.jpg",
|
||||
userName: "trickster",
|
||||
displayName: "Kuma Lisa",
|
||||
profileURL: "http://en.wikipedia.org/wiki/Kuma_Lisa"
|
||||
};
|
||||
}
|
||||
apiPort.postMessage({topic: "social.user-profile", data: profile});
|
||||
break;
|
||||
case "test-ambient-notification":
|
||||
apiPort.postMessage({topic: "social.ambient-notification", data: event.data.data});
|
||||
break;
|
||||
case "test-isVisible":
|
||||
sidebarPort.postMessage({topic: "test-isVisible"});
|
||||
break;
|
||||
case "test-isVisible-response":
|
||||
testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
|
||||
break;
|
||||
case "share-data-message":
|
||||
if (testPort)
|
||||
testPort.postMessage({topic:"got-share-data-message", result: event.data.result});
|
||||
break;
|
||||
case "manifest-get":
|
||||
apiPort.postMessage({topic: 'social.manifest-get'});
|
||||
break;
|
||||
case "worker.update":
|
||||
updatingManifest = true;
|
||||
apiPort.postMessage({topic: 'social.manifest-get'});
|
||||
break;
|
||||
case "social.manifest":
|
||||
if (updatingManifest) {
|
||||
updatingManifest = false;
|
||||
event.data.data.version = "2.0";
|
||||
apiPort.postMessage({topic: 'social.manifest-set', data: event.data.data});
|
||||
} else if (testPort) {
|
||||
testPort.postMessage({topic:"social.manifest", data: event.data.data});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -28,8 +28,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
|
||||
"resource://gre/modules/PageMetadata.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
|
||||
@ -95,7 +93,7 @@ this.Social = {
|
||||
// Retrieve the current set of providers, and set the current provider.
|
||||
SocialService.getOrderedProviderList(function (providers) {
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateWorkerState(SocialService.enabled);
|
||||
Social._updateEnabledState(SocialService.enabled);
|
||||
deferred.resolve(false);
|
||||
});
|
||||
} else {
|
||||
@ -113,15 +111,14 @@ this.Social = {
|
||||
}
|
||||
if (topic == "provider-enabled") {
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateWorkerState(true);
|
||||
Social._updateEnabledState(true);
|
||||
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||
return;
|
||||
}
|
||||
if (topic == "provider-disabled") {
|
||||
// a provider was removed from the list of providers, that does not
|
||||
// affect worker state for other providers
|
||||
// a provider was removed from the list of providers, update states
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateWorkerState(providers.length > 0);
|
||||
Social._updateEnabledState(providers.length > 0);
|
||||
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||
return;
|
||||
}
|
||||
@ -136,7 +133,7 @@ this.Social = {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_updateWorkerState: function(enable) {
|
||||
_updateEnabledState: function(enable) {
|
||||
for (let p of Social.providers) {
|
||||
p.enabled = enable;
|
||||
}
|
||||
@ -275,9 +272,6 @@ function CreateSocialStatusWidget(aId, aProvider) {
|
||||
node.setAttribute("oncommand", "SocialStatus.showPopup(this);");
|
||||
node.setAttribute("constrain-size", "true");
|
||||
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView))
|
||||
node.setAttribute("disabled", "true");
|
||||
|
||||
return node;
|
||||
}
|
||||
});
|
||||
|
@ -1,215 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an implementation of a "Shared Worker" using a remote browser
|
||||
* in the hidden DOM window. This is the implementation that lives in the
|
||||
* "chrome process". See FrameWorkerContent for code that lives in the
|
||||
* "content" process and which sets up a sandbox for the worker.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/MessagePortBase.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
|
||||
"resource://gre/modules/SocialService.jsm");
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["getFrameWorkerHandle"];
|
||||
|
||||
var workerCache = {}; // keyed by URL.
|
||||
var _nextPortId = 1;
|
||||
|
||||
// Retrieves a reference to a WorkerHandle associated with a FrameWorker and a
|
||||
// new ClientPort.
|
||||
this.getFrameWorkerHandle =
|
||||
function getFrameWorkerHandle(url, clientWindow, name, origin, exposeLocalStorage = false) {
|
||||
// prevent data/about urls - see bug 891516
|
||||
if (['http', 'https'].indexOf(Services.io.newURI(url, null, null).scheme) < 0)
|
||||
throw new Error("getFrameWorkerHandle requires http/https urls");
|
||||
|
||||
// See if we already have a worker with this URL.
|
||||
let existingWorker = workerCache[url];
|
||||
if (!existingWorker) {
|
||||
// create a remote browser and _Worker object - this will message the
|
||||
// remote browser to do the content side of things.
|
||||
let browserPromise = makeRemoteBrowser();
|
||||
let options = { url: url, name: name, origin: origin,
|
||||
exposeLocalStorage: exposeLocalStorage };
|
||||
|
||||
existingWorker = workerCache[url] = new _Worker(browserPromise, options);
|
||||
}
|
||||
|
||||
// message the content so it can establish a new connection with the worker.
|
||||
let portid = _nextPortId++;
|
||||
existingWorker.browserPromise.then(browser => {
|
||||
browser.messageManager.sendAsyncMessage("frameworker:connect",
|
||||
{ portId: portid });
|
||||
}).then(null, (ex) => {
|
||||
Cu.reportError("Could not send frameworker:connect: " + ex);
|
||||
});
|
||||
// return the pseudo worker object.
|
||||
let port = new ParentPort(portid, existingWorker.browserPromise, clientWindow);
|
||||
existingWorker.ports.set(portid, port);
|
||||
return new WorkerHandle(port, existingWorker);
|
||||
};
|
||||
|
||||
// A "_Worker" is an internal representation of a worker. It's never returned
|
||||
// directly to consumers.
|
||||
function _Worker(browserPromise, options) {
|
||||
this.browserPromise = browserPromise;
|
||||
this.options = options;
|
||||
this.ports = new Map();
|
||||
browserPromise.then(browser => {
|
||||
browser.addEventListener("oop-browser-crashed", () => {
|
||||
Cu.reportError("FrameWorker remote process crashed");
|
||||
notifyWorkerError(options.origin);
|
||||
});
|
||||
|
||||
let mm = browser.messageManager;
|
||||
// execute the content script and send the message to bootstrap the content
|
||||
// side of the world.
|
||||
mm.loadFrameScript("resource://gre/modules/FrameWorkerContent.js", true);
|
||||
mm.sendAsyncMessage("frameworker:init", this.options);
|
||||
mm.addMessageListener("frameworker:port-message", this);
|
||||
mm.addMessageListener("frameworker:notify-worker-error", this);
|
||||
});
|
||||
}
|
||||
|
||||
_Worker.prototype = {
|
||||
// Message handler.
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "frameworker:port-message":
|
||||
let port = this.ports.get(msg.data.portId);
|
||||
port._onmessage(msg.data.data);
|
||||
break;
|
||||
case "frameworker:notify-worker-error":
|
||||
notifyWorkerError(msg.data.origin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This WorkerHandle is exposed to consumers - it has the new port instance
|
||||
// the consumer uses to communicate with the worker.
|
||||
// public methods/properties on WorkerHandle should conform to the SharedWorker
|
||||
// api - currently that's just .port and .terminate()
|
||||
function WorkerHandle(port, worker) {
|
||||
this.port = port;
|
||||
this._worker = worker;
|
||||
}
|
||||
|
||||
WorkerHandle.prototype = {
|
||||
// A method to terminate the worker. The worker spec doesn't define a
|
||||
// callback to be made in the worker when this happens, so we just kill the
|
||||
// browser element.
|
||||
terminate: function terminate() {
|
||||
let url = this._worker.options.url;
|
||||
if (!(url in workerCache)) {
|
||||
// terminating an already terminated worker - ignore it
|
||||
return;
|
||||
}
|
||||
delete workerCache[url];
|
||||
// close all the ports we have handed out.
|
||||
for (let [portid, port] of this._worker.ports) {
|
||||
port.close();
|
||||
}
|
||||
this._worker.ports.clear();
|
||||
this._worker.ports = null;
|
||||
this._worker.browserPromise.then(browser => {
|
||||
let iframe = browser.ownerDocument.defaultView.frameElement;
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
});
|
||||
// wipe things out just incase other reference have snuck out somehow...
|
||||
this._worker.browserPromise = null;
|
||||
this._worker = null;
|
||||
}
|
||||
};
|
||||
|
||||
// The port that lives in the parent chrome process. The other end of this
|
||||
// port is the "client" port in the content process, which itself is just a
|
||||
// shim which shuttles messages to/from the worker itself.
|
||||
function ParentPort(portid, browserPromise, clientWindow) {
|
||||
this._clientWindow = clientWindow;
|
||||
this._browserPromise = browserPromise;
|
||||
AbstractPort.call(this, portid);
|
||||
}
|
||||
|
||||
ParentPort.prototype = {
|
||||
__proto__: AbstractPort.prototype,
|
||||
_portType: "parent",
|
||||
|
||||
_dopost: function(data) {
|
||||
this._browserPromise.then(browser => {
|
||||
browser.messageManager.sendAsyncMessage("frameworker:port-message", data);
|
||||
});
|
||||
},
|
||||
|
||||
_onerror: function(err) {
|
||||
Cu.reportError("FrameWorker: Port " + this + " handler failed: " + err + "\n" + err.stack);
|
||||
},
|
||||
|
||||
_JSONParse: function(data) {
|
||||
if (this._clientWindow) {
|
||||
return XPCNativeWrapper.unwrap(this._clientWindow).JSON.parse(data);
|
||||
}
|
||||
return JSON.parse(data);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
if (this._closed) {
|
||||
return; // already closed.
|
||||
}
|
||||
// a leaky abstraction due to the worker spec not specifying how the
|
||||
// other end of a port knows it is closing.
|
||||
this.postMessage({topic: "social.port-closing"});
|
||||
AbstractPort.prototype.close.call(this);
|
||||
this._clientWindow = null;
|
||||
// this._pendingMessagesOutgoing should still be drained, as a closed
|
||||
// port will still get "entangled" quickly enough to deliver the messages.
|
||||
}
|
||||
}
|
||||
|
||||
// Make the <browser remote="true"> element that hosts the worker.
|
||||
function makeRemoteBrowser() {
|
||||
let deferred = Promise.defer();
|
||||
let hiddenDoc = Services.appShell.hiddenDOMWindow.document;
|
||||
// Create a HTML iframe with a chrome URL, then this can host the browser.
|
||||
let iframe = hiddenDoc.createElementNS(HTML_NS, "iframe");
|
||||
iframe.setAttribute("src", "chrome://global/content/mozilla.xhtml");
|
||||
iframe.addEventListener("load", function onLoad() {
|
||||
iframe.removeEventListener("load", onLoad, true);
|
||||
let browser = iframe.contentDocument.createElementNS(XUL_NS, "browser");
|
||||
browser.setAttribute("type", "content");
|
||||
browser.setAttribute("disableglobalhistory", "true");
|
||||
browser.setAttribute("remote", "true");
|
||||
|
||||
iframe.contentDocument.documentElement.appendChild(browser);
|
||||
deferred.resolve(browser);
|
||||
}, true);
|
||||
hiddenDoc.documentElement.appendChild(iframe);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function notifyWorkerError(origin) {
|
||||
// Try to retrieve the worker's associated provider, if it has one, to set its
|
||||
// error state.
|
||||
SocialService.getProvider(origin, function (provider) {
|
||||
if (provider)
|
||||
provider.errorState = "frameworker-error";
|
||||
Services.obs.notifyObservers(null, "social:frameworker-error", origin);
|
||||
});
|
||||
}
|
@ -1,414 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
// the singleton frameworker, available for (ab)use by tests.
|
||||
var frameworker;
|
||||
|
||||
(function () { // bug 673569 workaround :(
|
||||
|
||||
/*
|
||||
* This is an implementation of a "Shared Worker" using a remote <browser>
|
||||
* element hosted in the hidden DOM window. This is the "content script"
|
||||
* implementation - it runs in the child process but has chrome permissions.
|
||||
*
|
||||
* A set of new APIs that simulate a shared worker are introduced to a sandbox
|
||||
* by cloning methods from the worker's JS origin.
|
||||
*/
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/MessagePortBase.jsm");
|
||||
|
||||
function navigate(url) {
|
||||
let webnav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
webnav.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* FrameWorker
|
||||
*
|
||||
* A FrameWorker is a <browser> element hosted by the hiddenWindow.
|
||||
* It is constructed with the URL of some JavaScript that will be run in
|
||||
* the context of the browser; the script does not have a full DOM but is
|
||||
* instead run in a sandbox that has a select set of methods cloned from the
|
||||
* URL's domain.
|
||||
*/
|
||||
function FrameWorker(url, name, origin, exposeLocalStorage) {
|
||||
this.url = url;
|
||||
this.name = name || url;
|
||||
this.ports = new Map(); // all unclosed ports, including ones yet to be entangled
|
||||
this.loaded = false;
|
||||
this.origin = origin;
|
||||
this._injectController = null;
|
||||
this.exposeLocalStorage = exposeLocalStorage;
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
FrameWorker.prototype = {
|
||||
load: function FrameWorker_loadWorker() {
|
||||
this._injectController = function(doc, topic, data) {
|
||||
if (!doc.defaultView || doc.defaultView != content) {
|
||||
return;
|
||||
}
|
||||
this._maybeRemoveInjectController();
|
||||
try {
|
||||
this.createSandbox();
|
||||
} catch (e) {
|
||||
Cu.reportError("FrameWorker: failed to create sandbox for " + this.url + ". " + e);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
Services.obs.addObserver(this._injectController, "document-element-inserted", false);
|
||||
navigate(this.url);
|
||||
},
|
||||
|
||||
_maybeRemoveInjectController: function() {
|
||||
if (this._injectController) {
|
||||
Services.obs.removeObserver(this._injectController, "document-element-inserted");
|
||||
this._injectController = null;
|
||||
}
|
||||
},
|
||||
|
||||
createSandbox: function createSandbox() {
|
||||
let workerWindow = content;
|
||||
let sandbox = new Cu.Sandbox(workerWindow);
|
||||
|
||||
// copy the window apis onto the sandbox namespace only functions or
|
||||
// objects that are naturally a part of an iframe, I'm assuming they are
|
||||
// safe to import this way
|
||||
let workerAPI = ['WebSocket', 'atob', 'btoa',
|
||||
'clearInterval', 'clearTimeout', 'dump',
|
||||
'setInterval', 'setTimeout', 'XMLHttpRequest',
|
||||
'FileReader', 'Blob', 'EventSource', 'indexedDB',
|
||||
'location', 'Worker'];
|
||||
|
||||
// Only expose localStorage if the caller opted-in
|
||||
if (this.exposeLocalStorage) {
|
||||
workerAPI.push('localStorage');
|
||||
}
|
||||
|
||||
// Bug 798660 - XHR, WebSocket and Worker have issues in a sandbox and need
|
||||
// to be unwrapped to work
|
||||
let needsWaive = ['XMLHttpRequest', 'WebSocket', 'Worker' ];
|
||||
// Methods need to be bound with the proper |this|.
|
||||
let needsBind = ['atob', 'btoa', 'dump', 'setInterval', 'clearInterval',
|
||||
'setTimeout', 'clearTimeout'];
|
||||
workerAPI.forEach(function(fn) {
|
||||
try {
|
||||
if (needsWaive.indexOf(fn) != -1)
|
||||
sandbox[fn] = XPCNativeWrapper.unwrap(workerWindow)[fn];
|
||||
else if (needsBind.indexOf(fn) != -1)
|
||||
sandbox[fn] = workerWindow[fn].bind(workerWindow);
|
||||
else
|
||||
sandbox[fn] = workerWindow[fn];
|
||||
}
|
||||
catch(e) {
|
||||
Cu.reportError("FrameWorker: failed to import API "+fn+"\n"+e+"\n");
|
||||
}
|
||||
});
|
||||
// the "navigator" object in a worker is a subset of the full navigator;
|
||||
// specifically, just the interfaces 'NavigatorID' and 'NavigatorOnLine'
|
||||
let navigator = Cu.cloneInto({
|
||||
// interface NavigatorID
|
||||
appName: workerWindow.navigator.appName,
|
||||
appVersion: workerWindow.navigator.appVersion,
|
||||
platform: workerWindow.navigator.platform,
|
||||
userAgent: workerWindow.navigator.userAgent,
|
||||
}, sandbox);
|
||||
Object.defineProperty(Cu.waiveXrays(navigator), 'onLine', {
|
||||
configurable: true, enumerable: true,
|
||||
get: Cu.exportFunction(() => workerWindow.navigator.onLine, sandbox)
|
||||
});
|
||||
sandbox.navigator = navigator;
|
||||
|
||||
// Our importScripts function needs to 'eval' the script code from inside
|
||||
// a function, but using eval() directly means functions in the script
|
||||
// don't end up in the global scope.
|
||||
sandbox._evalInSandbox = function(s, url) {
|
||||
let baseURI = Services.io.newURI(workerWindow.location.href, null, null);
|
||||
Cu.evalInSandbox(s, sandbox, "1.8",
|
||||
Services.io.newURI(url, null, baseURI).spec, 1);
|
||||
};
|
||||
|
||||
// and we delegate ononline and onoffline events to the worker.
|
||||
// See http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerglobalscope
|
||||
workerWindow.addEventListener('offline', function fw_onoffline(event) {
|
||||
Cu.evalInSandbox("onoffline();", sandbox);
|
||||
}, false);
|
||||
workerWindow.addEventListener('online', function fw_ononline(event) {
|
||||
Cu.evalInSandbox("ononline();", sandbox);
|
||||
}, false);
|
||||
|
||||
sandbox._postMessage = function fw_postMessage(d, o) {
|
||||
workerWindow.postMessage(d, o)
|
||||
};
|
||||
sandbox._addEventListener = function fw_addEventListener(t, l, c) {
|
||||
workerWindow.addEventListener(t, l, c)
|
||||
};
|
||||
|
||||
// Note we don't need to stash |sandbox| in |this| as the unload handler
|
||||
// has a reference in its closure, so it can't die until that handler is
|
||||
// removed - at which time we've explicitly killed it anyway.
|
||||
let worker = this;
|
||||
|
||||
workerWindow.addEventListener("DOMContentLoaded", function loadListener() {
|
||||
workerWindow.removeEventListener("DOMContentLoaded", loadListener);
|
||||
|
||||
// no script, error out now rather than creating ports, etc
|
||||
let scriptText = workerWindow.document.body.textContent.trim();
|
||||
if (!scriptText) {
|
||||
Cu.reportError("FrameWorker: Empty worker script received");
|
||||
notifyWorkerError();
|
||||
return;
|
||||
}
|
||||
|
||||
// now that we've got the script text, remove it from the DOM;
|
||||
// no need for it to keep occupying memory there
|
||||
workerWindow.document.body.textContent = "";
|
||||
|
||||
// the content has loaded the js file as text - first inject the magic
|
||||
// port-handling code into the sandbox.
|
||||
try {
|
||||
Services.scriptloader.loadSubScript("resource://gre/modules/MessagePortBase.jsm", sandbox);
|
||||
Services.scriptloader.loadSubScript("resource://gre/modules/MessagePortWorker.js", sandbox);
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError("FrameWorker: Error injecting port code into content side of the worker: " + e + "\n" + e.stack);
|
||||
notifyWorkerError();
|
||||
return;
|
||||
}
|
||||
|
||||
// and wire up the client message handling.
|
||||
try {
|
||||
initClientMessageHandler();
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError("FrameWorker: Error setting up event listener for chrome side of the worker: " + e + "\n" + e.stack);
|
||||
notifyWorkerError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Now get the worker js code and eval it into the sandbox
|
||||
try {
|
||||
Cu.evalInSandbox(scriptText, sandbox, "1.8", workerWindow.location.href, 1);
|
||||
} catch (e) {
|
||||
Cu.reportError("FrameWorker: Error evaluating worker script for " + worker.name + ": " + e + "; " +
|
||||
(e.lineNumber ? ("Line #" + e.lineNumber) : "") +
|
||||
(e.stack ? ("\n" + e.stack) : ""));
|
||||
notifyWorkerError();
|
||||
return;
|
||||
}
|
||||
|
||||
// so finally we are ready to roll - dequeue all the pending connects
|
||||
worker.loaded = true;
|
||||
for (let [,port] of worker.ports) { // enumeration is in insertion order
|
||||
if (!port._entangled) {
|
||||
try {
|
||||
port._createWorkerAndEntangle(worker);
|
||||
}
|
||||
catch(e) {
|
||||
Cu.reportError("FrameWorker: Failed to entangle worker port: " + e + "\n" + e.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// the 'unload' listener cleans up the worker and the sandbox. This
|
||||
// will be triggered by the window unloading as part of shutdown or reload.
|
||||
workerWindow.addEventListener("unload", function unloadListener() {
|
||||
workerWindow.removeEventListener("unload", unloadListener);
|
||||
worker.loaded = false;
|
||||
// No need to close ports - the worker probably wont see a
|
||||
// social.port-closing message and certainly isn't going to have time to
|
||||
// do anything if it did see it.
|
||||
worker.ports.clear();
|
||||
if (sandbox) {
|
||||
Cu.nukeSandbox(sandbox);
|
||||
sandbox = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const FrameWorkerManager = {
|
||||
init: function() {
|
||||
// first, setup the docShell to disable some types of content
|
||||
docShell.allowAuth = false;
|
||||
docShell.allowPlugins = false;
|
||||
docShell.allowImages = false;
|
||||
docShell.allowMedia = false;
|
||||
docShell.allowWindowControl = false;
|
||||
|
||||
addMessageListener("frameworker:init", this._onInit);
|
||||
addMessageListener("frameworker:connect", this._onConnect);
|
||||
addMessageListener("frameworker:port-message", this._onPortMessage);
|
||||
addMessageListener("frameworker:cookie-get", this._onCookieGet);
|
||||
},
|
||||
|
||||
// This new frameworker is being created. This should only be called once.
|
||||
_onInit: function(msg) {
|
||||
let {url, name, origin, exposeLocalStorage} = msg.data;
|
||||
frameworker = new FrameWorker(url, name, origin, exposeLocalStorage);
|
||||
},
|
||||
|
||||
// A new port is being established for this frameworker.
|
||||
_onConnect: function(msg) {
|
||||
let port = new ClientPort(msg.data.portId);
|
||||
frameworker.ports.set(msg.data.portId, port);
|
||||
if (frameworker.loaded && !frameworker.reloading)
|
||||
port._createWorkerAndEntangle(frameworker);
|
||||
},
|
||||
|
||||
// A message related to a port.
|
||||
_onPortMessage: function(msg) {
|
||||
// find the "client" port for this message and have it post it into
|
||||
// the worker.
|
||||
let port = frameworker.ports.get(msg.data.portId);
|
||||
port._dopost(msg.data);
|
||||
},
|
||||
|
||||
_onCookieGet: function(msg) {
|
||||
sendAsyncMessage("frameworker:cookie-get-response", content.document.cookie);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
FrameWorkerManager.init();
|
||||
|
||||
// This is the message listener for the chrome side of the world - ie, the
|
||||
// port that exists with chrome permissions inside the <browser/> (ie, in the
|
||||
// content process if a remote browser is used).
|
||||
function initClientMessageHandler() {
|
||||
function _messageHandler(event) {
|
||||
// We will ignore all messages destined for otherType.
|
||||
let data = event.data;
|
||||
let portid = data.portId;
|
||||
let port;
|
||||
if (!data.portFromType || data.portFromType !== "worker") {
|
||||
// this is a message posted by ourself so ignore it.
|
||||
return;
|
||||
}
|
||||
switch (data.portTopic) {
|
||||
// No "port-create" here - client ports are created explicitly.
|
||||
case "port-connection-error":
|
||||
// onconnect failed, we cannot connect the port, the worker has
|
||||
// become invalid
|
||||
notifyWorkerError();
|
||||
break;
|
||||
case "port-close":
|
||||
// the worker side of the port was closed, so close this side too.
|
||||
port = frameworker.ports.get(portid);
|
||||
if (!port) {
|
||||
// port already closed (which will happen when we call port.close()
|
||||
// below - the worker side will send us this message but we've
|
||||
// already closed it.)
|
||||
return;
|
||||
}
|
||||
frameworker.ports.delete(portid);
|
||||
port.close();
|
||||
break;
|
||||
|
||||
case "port-message":
|
||||
// the client posted a message to this worker port.
|
||||
port = frameworker.ports.get(portid);
|
||||
if (!port) {
|
||||
return;
|
||||
}
|
||||
port._onmessage(data.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// this can probably go once debugged and working correctly!
|
||||
function messageHandler(event) {
|
||||
try {
|
||||
_messageHandler(event);
|
||||
} catch (ex) {
|
||||
Cu.reportError("FrameWorker: Error handling client port control message: " + ex + "\n" + ex.stack);
|
||||
}
|
||||
}
|
||||
content.addEventListener('message', messageHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* ClientPort
|
||||
*
|
||||
* Client side of the entangled ports. This is just a shim that sends messages
|
||||
* back to the "parent" port living in the chrome process.
|
||||
*
|
||||
* constructor:
|
||||
* @param {integer} portid
|
||||
*/
|
||||
function ClientPort(portid) {
|
||||
// messages posted to the worker before the worker has loaded.
|
||||
this._pendingMessagesOutgoing = [];
|
||||
AbstractPort.call(this, portid);
|
||||
}
|
||||
|
||||
ClientPort.prototype = {
|
||||
__proto__: AbstractPort.prototype,
|
||||
_portType: "client",
|
||||
// _entangled records if the port has ever been entangled (although may be
|
||||
// reset during a reload).
|
||||
_entangled: false,
|
||||
|
||||
_createWorkerAndEntangle: function fw_ClientPort_createWorkerAndEntangle(worker) {
|
||||
this._entangled = true;
|
||||
this._postControlMessage("port-create");
|
||||
for (let message of this._pendingMessagesOutgoing) {
|
||||
this._dopost(message);
|
||||
}
|
||||
this._pendingMessagesOutgoing = [];
|
||||
// The client side of the port might have been closed before it was
|
||||
// "entangled" with the worker, in which case we need to disentangle it
|
||||
if (this._closed) {
|
||||
worker.ports.delete(this._portid);
|
||||
}
|
||||
},
|
||||
|
||||
_dopost: function fw_ClientPort_dopost(data) {
|
||||
if (!this._entangled) {
|
||||
this._pendingMessagesOutgoing.push(data);
|
||||
} else {
|
||||
content.postMessage(data, "*");
|
||||
}
|
||||
},
|
||||
|
||||
// we are just a "shim" - any messages we get are just forwarded back to
|
||||
// the chrome parent process.
|
||||
_onmessage: function(data) {
|
||||
sendAsyncMessage("frameworker:port-message", {portId: this._portid, data: data});
|
||||
},
|
||||
|
||||
_onerror: function fw_ClientPort_onerror(err) {
|
||||
Cu.reportError("FrameWorker: Port " + this + " handler failed: " + err + "\n" + err.stack);
|
||||
},
|
||||
|
||||
close: function fw_ClientPort_close() {
|
||||
if (this._closed) {
|
||||
return; // already closed.
|
||||
}
|
||||
// a leaky abstraction due to the worker spec not specifying how the
|
||||
// other end of a port knows it is closing.
|
||||
this.postMessage({topic: "social.port-closing"});
|
||||
AbstractPort.prototype.close.call(this);
|
||||
// this._pendingMessagesOutgoing should still be drained, as a closed
|
||||
// port will still get "entangled" quickly enough to deliver the messages.
|
||||
}
|
||||
}
|
||||
|
||||
function notifyWorkerError() {
|
||||
sendAsyncMessage("frameworker:notify-worker-error", {origin: frameworker.origin});
|
||||
}
|
||||
|
||||
}());
|
@ -1,110 +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/. */
|
||||
|
||||
// Code that is shared between clients and workers.
|
||||
this.EXPORTED_SYMBOLS = ["AbstractPort"];
|
||||
|
||||
this.AbstractPort = function AbstractPort(portid) {
|
||||
this._portid = portid;
|
||||
this._handler = undefined;
|
||||
this._closed = false;
|
||||
// pending messages sent to this port before it has a message handler.
|
||||
this._pendingMessagesIncoming = [];
|
||||
};
|
||||
|
||||
AbstractPort.prototype = {
|
||||
_portType: null, // set by a subclass.
|
||||
// abstract methods to be overridden.
|
||||
_dopost: function fw_AbstractPort_dopost(data) {
|
||||
throw new Error("not implemented");
|
||||
},
|
||||
_onerror: function fw_AbstractPort_onerror(err) {
|
||||
throw new Error("not implemented");
|
||||
},
|
||||
|
||||
// and concrete methods shared by client and workers.
|
||||
toString: function fw_AbstractPort_toString() {
|
||||
return "MessagePort(portType='" + this._portType + "', portId="
|
||||
+ this._portid + (this._closed ? ", closed=true" : "") + ")";
|
||||
},
|
||||
_JSONParse: function fw_AbstractPort_JSONParse(data) {
|
||||
return JSON.parse(data);
|
||||
},
|
||||
|
||||
_postControlMessage: function fw_AbstractPort_postControlMessage(topic, data) {
|
||||
let postData = {
|
||||
portTopic: topic,
|
||||
portId: this._portid,
|
||||
portFromType: this._portType,
|
||||
data: data
|
||||
};
|
||||
this._dopost(postData);
|
||||
},
|
||||
|
||||
_onmessage: function fw_AbstractPort_onmessage(data) {
|
||||
// See comments in postMessage below - we work around a cloning
|
||||
// issue by using JSON for these messages.
|
||||
// Further, we allow the workers to override exactly how the JSON parsing
|
||||
// is done - we try and do such parsing in the client window so things
|
||||
// like prototype overrides on Array work as expected.
|
||||
if (!this._handler) {
|
||||
this._pendingMessagesIncoming.push(data);
|
||||
} else {
|
||||
data = this._JSONParse(data);
|
||||
try {
|
||||
this._handler({
|
||||
data: data,
|
||||
__exposedProps__: {
|
||||
data: 'r'
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
this._onerror(ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
set onmessage(handler) { // property setter for onmessage
|
||||
this._handler = handler;
|
||||
while (this._pendingMessagesIncoming.length) {
|
||||
this._onmessage(this._pendingMessagesIncoming.shift());
|
||||
}
|
||||
},
|
||||
get onmessage() {
|
||||
return this._handler;
|
||||
},
|
||||
|
||||
/**
|
||||
* postMessage
|
||||
*
|
||||
* Send data to the onmessage handler on the other end of the port. The
|
||||
* data object should have a topic property.
|
||||
*
|
||||
* @param {jsobj} data
|
||||
*/
|
||||
postMessage: function fw_AbstractPort_postMessage(data) {
|
||||
if (this._closed) {
|
||||
throw new Error("port is closed");
|
||||
}
|
||||
// There seems to be an issue with passing objects directly and letting
|
||||
// the structured clone thing work - we sometimes get:
|
||||
// [Exception... "The object could not be cloned." code: "25" nsresult: "0x80530019 (DataCloneError)"]
|
||||
// The best guess is that this happens when funky things have been added to the prototypes.
|
||||
// It doesn't happen for our "control" messages, only in messages from
|
||||
// content - so we explicitly use JSON on these messages as that avoids
|
||||
// the problem.
|
||||
this._postControlMessage("port-message", JSON.stringify(data));
|
||||
},
|
||||
|
||||
close: function fw_AbstractPort_close() {
|
||||
if (this._closed) {
|
||||
return; // already closed.
|
||||
}
|
||||
this._postControlMessage("port-close");
|
||||
// and clean myself up.
|
||||
this._handler = null;
|
||||
this._pendingMessagesIncoming = [];
|
||||
this._closed = true;
|
||||
}
|
||||
};
|
@ -1,110 +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/. */
|
||||
|
||||
// Note: this is never instantiated in chrome - the source is sent across
|
||||
// to the worker and it is evaluated there and created in response to a
|
||||
// port-create message we send.
|
||||
function WorkerPort(portid) {
|
||||
AbstractPort.call(this, portid);
|
||||
}
|
||||
|
||||
WorkerPort.prototype = {
|
||||
__proto__: AbstractPort.prototype,
|
||||
_portType: "worker",
|
||||
|
||||
_dopost: function fw_WorkerPort_dopost(data) {
|
||||
// postMessage is injected into the sandbox.
|
||||
_postMessage(data, "*");
|
||||
},
|
||||
|
||||
_onerror: function fw_WorkerPort_onerror(err) {
|
||||
// We throw an object that "derives" from the exception, but with
|
||||
// a more detailed message.
|
||||
throw {message: "Port " + this + " handler failed: " + err.message, __proto__: err};
|
||||
}
|
||||
}
|
||||
|
||||
function importScripts() {
|
||||
for (var i=0; i < arguments.length; i++) {
|
||||
// load the url *synchronously*
|
||||
var scriptURL = arguments[i];
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', scriptURL, false);
|
||||
xhr.onreadystatechange = function(aEvt) {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200 || xhr.status == 0) {
|
||||
_evalInSandbox(xhr.responseText, scriptURL);
|
||||
}
|
||||
else {
|
||||
throw new Error("Unable to importScripts ["+scriptURL+"], status " + xhr.status)
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
}
|
||||
|
||||
// This function is magically injected into the sandbox and used there.
|
||||
// Thus, it is only ever dealing with "worker" ports.
|
||||
function __initWorkerMessageHandler() {
|
||||
|
||||
let ports = {}; // all "worker" ports currently alive, keyed by ID.
|
||||
|
||||
function messageHandler(event) {
|
||||
// We will ignore all messages destined for otherType.
|
||||
let data = event.data;
|
||||
let portid = data.portId;
|
||||
let port;
|
||||
if (!data.portFromType || data.portFromType === "worker") {
|
||||
// this is a message posted by ourself so ignore it.
|
||||
return;
|
||||
}
|
||||
switch (data.portTopic) {
|
||||
case "port-create":
|
||||
// a new port was created on the "client" side - create a new worker
|
||||
// port and store it in the map
|
||||
port = new WorkerPort(portid);
|
||||
ports[portid] = port;
|
||||
// and call the "onconnect" handler.
|
||||
try {
|
||||
onconnect({ports: [port]});
|
||||
} catch(e) {
|
||||
// we have a bad worker and cannot continue, we need to signal
|
||||
// an error
|
||||
port._postControlMessage("port-connection-error", JSON.stringify(e.toString()));
|
||||
throw e;
|
||||
}
|
||||
break;
|
||||
|
||||
case "port-close":
|
||||
// the client side of the port was closed, so close this side too.
|
||||
port = ports[portid];
|
||||
if (!port) {
|
||||
// port already closed (which will happen when we call port.close()
|
||||
// below - the client side will send us this message but we've
|
||||
// already closed it.)
|
||||
return;
|
||||
}
|
||||
delete ports[portid];
|
||||
port.close();
|
||||
break;
|
||||
|
||||
case "port-message":
|
||||
// the client posted a message to this worker port.
|
||||
port = ports[portid];
|
||||
if (!port) {
|
||||
// port must be closed - this shouldn't happen!
|
||||
return;
|
||||
}
|
||||
port._onmessage(data.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// addEventListener is injected into the sandbox.
|
||||
_addEventListener('message', messageHandler);
|
||||
}
|
||||
__initWorkerMessageHandler();
|
@ -72,8 +72,7 @@ function injectController(doc, topic, data) {
|
||||
}
|
||||
|
||||
// we always handle window.close on social content, even if they are not
|
||||
// "enabled". "enabled" is about the worker state and a provider may
|
||||
// still be in e.g. the share panel without having their worker enabled.
|
||||
// "enabled".
|
||||
hookWindowCloseForPanelClose(window);
|
||||
|
||||
SocialService.getProvider(doc.nodePrincipal.origin, function(provider) {
|
||||
@ -98,47 +97,7 @@ function attachToWindow(provider, targetWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
let port = provider.workerURL ? provider.getWorkerPort(targetWindow) : null;
|
||||
|
||||
let mozSocialObj = {
|
||||
// Use a method for backwards compat with existing providers, but we
|
||||
// should deprecate this in favor of a simple .port getter.
|
||||
getWorker: {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function() {
|
||||
|
||||
// We do a bunch of hacky stuff to expose this API to content without
|
||||
// relying on ChromeObjectWrapper functionality that is now unsupported.
|
||||
// The content-facing API here should really move to JS-Implemented
|
||||
// WebIDL.
|
||||
let workerAPI = Cu.cloneInto({
|
||||
port: {
|
||||
postMessage: port.postMessage.bind(port),
|
||||
close: port.close.bind(port),
|
||||
toString: port.toString.bind(port)
|
||||
}
|
||||
}, targetWindow, {cloneFunctions: true});
|
||||
|
||||
// Jump through hoops to define the accessor property.
|
||||
let abstractPortPrototype = Object.getPrototypeOf(Object.getPrototypeOf(port));
|
||||
let desc = Object.getOwnPropertyDescriptor(port.__proto__.__proto__, 'onmessage');
|
||||
desc.get = Cu.exportFunction(desc.get.bind(port), targetWindow);
|
||||
desc.set = Cu.exportFunction(desc.set.bind(port), targetWindow);
|
||||
Object.defineProperty(workerAPI.wrappedJSObject.port, 'onmessage', desc);
|
||||
|
||||
return workerAPI;
|
||||
}
|
||||
},
|
||||
hasBeenIdleFor: {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
openChatWindow: {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
@ -238,15 +197,6 @@ function attachToWindow(provider, targetWindow) {
|
||||
delete targetWindow.navigator.wrappedJSObject.mozSocial;
|
||||
return targetWindow.navigator.wrappedJSObject.mozSocial = contentObj;
|
||||
});
|
||||
|
||||
if (port) {
|
||||
targetWindow.addEventListener("unload", function () {
|
||||
// We want to close the port, but also want the target window to be
|
||||
// able to use the port during an unload event they setup - so we
|
||||
// set a timer which will fire after the unload events have all fired.
|
||||
schedule(function () { port.close(); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function hookWindowCloseForPanelClose(targetWindow) {
|
||||
|
@ -16,8 +16,6 @@ const ADDON_TYPE_SERVICE = "service";
|
||||
const ID_SUFFIX = "@services.mozilla.org";
|
||||
const STRING_TYPE_NAME = "type.%ID%.name";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WorkerAPI", "resource://gre/modules/WorkerAPI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MozSocialAPI", "resource://gre/modules/MozSocialAPI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "closeAllChatWindows", "resource://gre/modules/MozSocialAPI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
|
||||
@ -505,7 +503,7 @@ this.SocialService = {
|
||||
},
|
||||
|
||||
_manifestFromData: function(type, data, installOrigin) {
|
||||
let featureURLs = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL'];
|
||||
let featureURLs = ['sidebarURL', 'shareURL', 'statusURL', 'markURL'];
|
||||
let resolveURLs = featureURLs.concat(['postActivationURL']);
|
||||
|
||||
if (type == 'directory' || type == 'internal') {
|
||||
@ -665,8 +663,6 @@ this.SocialService = {
|
||||
// overwrite the existing provider then notify the front end so it can
|
||||
// handle any reload that might be necessary.
|
||||
if (ActiveProviders.has(manifest.origin)) {
|
||||
// unload the worker prior to replacing the provider instance, also
|
||||
// ensures the workerapi instance is terminated.
|
||||
let provider = SocialServiceInternal.providers[manifest.origin];
|
||||
provider.enabled = false;
|
||||
provider = new SocialProvider(manifest);
|
||||
@ -687,8 +683,7 @@ this.SocialService = {
|
||||
};
|
||||
|
||||
/**
|
||||
* The SocialProvider object represents a social provider, and allows
|
||||
* access to its FrameWorker (if it has one).
|
||||
* The SocialProvider object represents a social provider.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jsobj} object representing the manifest file describing this provider
|
||||
@ -709,7 +704,6 @@ function SocialProvider(input) {
|
||||
this.iconURL = input.iconURL;
|
||||
this.icon32URL = input.icon32URL;
|
||||
this.icon64URL = input.icon64URL;
|
||||
this.workerURL = input.workerURL;
|
||||
this.sidebarURL = input.sidebarURL;
|
||||
this.shareURL = input.shareURL;
|
||||
this.statusURL = input.statusURL;
|
||||
@ -724,11 +718,6 @@ function SocialProvider(input) {
|
||||
this.errorState = null;
|
||||
this.frecency = 0;
|
||||
|
||||
// this provider has localStorage access in the worker if listed in the
|
||||
// whitelist
|
||||
let whitelist = Services.prefs.getCharPref("social.whitelist").split(',');
|
||||
this.blessed = whitelist.indexOf(this.origin) >= 0;
|
||||
|
||||
try {
|
||||
this.domain = etld.getBaseDomainFromHost(originUri.host);
|
||||
} catch(e) {
|
||||
@ -745,8 +734,7 @@ SocialProvider.prototype = {
|
||||
Services.obs.notifyObservers(null, "social:provider-reload", this.origin);
|
||||
},
|
||||
|
||||
// Provider enabled/disabled state. Disabled providers do not have active
|
||||
// connections to their FrameWorkers.
|
||||
// Provider enabled/disabled state.
|
||||
_enabled: false,
|
||||
get enabled() {
|
||||
return this._enabled;
|
||||
@ -776,81 +764,14 @@ SocialProvider.prototype = {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// Reference to a workerAPI object for this provider. Null if the provider has
|
||||
// no FrameWorker, or is disabled.
|
||||
workerAPI: null,
|
||||
|
||||
// Contains information related to the user's profile. Populated by the
|
||||
// workerAPI via updateUserProfile.
|
||||
// Properties:
|
||||
// iconURL, portrait, userName, displayName, profileURL
|
||||
// See https://github.com/mozilla/socialapi-dev/blob/develop/docs/socialAPI.md
|
||||
// A value of null or an empty object means 'user not logged in'.
|
||||
// A value of undefined means the service has not yet told us the status of
|
||||
// the profile (ie, the service is still loading/initing, or the provider has
|
||||
// no FrameWorker)
|
||||
// This distinction might be used to cache certain data between runs - eg,
|
||||
// browser-social.js caches the notification icons so they can be displayed
|
||||
// quickly at startup without waiting for the provider to initialize -
|
||||
// 'undefined' means 'ok to use cached values' versus 'null' meaning 'cached
|
||||
// values aren't to be used as the user is logged out'.
|
||||
profile: undefined,
|
||||
|
||||
// Map of objects describing the provider's notification icons, whose
|
||||
// properties include:
|
||||
// name, iconURL, counter, contentPanel
|
||||
// See https://developer.mozilla.org/en-US/docs/Social_API
|
||||
ambientNotificationIcons: null,
|
||||
|
||||
// Called by the workerAPI to update our profile information.
|
||||
updateUserProfile: function(profile) {
|
||||
if (!profile)
|
||||
profile = {};
|
||||
let accountChanged = !this.profile || this.profile.userName != profile.userName;
|
||||
this.profile = profile;
|
||||
|
||||
// Sanitize the portrait from any potential script-injection.
|
||||
if (profile.portrait) {
|
||||
try {
|
||||
let portraitUri = Services.io.newURI(profile.portrait, null, null);
|
||||
|
||||
let scheme = portraitUri ? portraitUri.scheme : "";
|
||||
if (scheme != "data" && scheme != "http" && scheme != "https") {
|
||||
profile.portrait = "";
|
||||
}
|
||||
} catch (ex) {
|
||||
profile.portrait = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (profile.iconURL)
|
||||
this.iconURL = profile.iconURL;
|
||||
|
||||
if (!profile.displayName)
|
||||
profile.displayName = profile.userName;
|
||||
|
||||
// if no userName, consider this a logged out state, emtpy the
|
||||
// users ambient notifications. notify both profile and ambient
|
||||
// changes to clear everything
|
||||
if (!profile.userName) {
|
||||
this.profile = {};
|
||||
this.ambientNotificationIcons = {};
|
||||
Services.obs.notifyObservers(null, "social:ambient-notification-changed", this.origin);
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "social:profile-changed", this.origin);
|
||||
if (accountChanged)
|
||||
closeAllChatWindows(this);
|
||||
},
|
||||
|
||||
haveLoggedInUser: function () {
|
||||
return !!(this.profile && this.profile.userName);
|
||||
},
|
||||
|
||||
// Called by the workerAPI to add/update a notification icon.
|
||||
setAmbientNotification: function(notification) {
|
||||
if (!this.profile.userName)
|
||||
throw new Error("unable to set notifications while logged out");
|
||||
if (!this.ambientNotificationIcons[notification.name] &&
|
||||
Object.keys(this.ambientNotificationIcons).length >= 3) {
|
||||
throw new Error("ambient notification limit reached");
|
||||
@ -862,47 +783,11 @@ SocialProvider.prototype = {
|
||||
|
||||
// Internal helper methods
|
||||
_activate: function _activate() {
|
||||
// Initialize the workerAPI and its port first, so that its initialization
|
||||
// occurs before any other messages are processed by other ports.
|
||||
let workerAPIPort = this.getWorkerPort();
|
||||
if (workerAPIPort)
|
||||
this.workerAPI = new WorkerAPI(this, workerAPIPort);
|
||||
},
|
||||
|
||||
_terminate: function _terminate() {
|
||||
closeAllChatWindows(this);
|
||||
if (this.workerURL) {
|
||||
try {
|
||||
getFrameWorkerHandle(this.workerURL).terminate();
|
||||
} catch (e) {
|
||||
Cu.reportError("SocialProvider FrameWorker termination failed: " + e);
|
||||
}
|
||||
}
|
||||
if (this.workerAPI) {
|
||||
this.workerAPI.terminate();
|
||||
}
|
||||
this.errorState = null;
|
||||
this.workerAPI = null;
|
||||
this.profile = undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Instantiates a FrameWorker for the provider if one doesn't exist, and
|
||||
* returns a reference to a new port to that FrameWorker.
|
||||
*
|
||||
* Returns null if this provider has no workerURL, or is disabled.
|
||||
*
|
||||
* @param {DOMWindow} window (optional)
|
||||
*/
|
||||
getWorkerPort: function getWorkerPort(window) {
|
||||
if (!this.workerURL || !this.enabled)
|
||||
return null;
|
||||
// Only allow localStorage in the frameworker for blessed providers
|
||||
let allowLocalStorage = this.blessed;
|
||||
let handle = getFrameWorkerHandle(this.workerURL, window,
|
||||
"SocialProvider:" + this.origin, this.origin,
|
||||
allowLocalStorage);
|
||||
return handle.port;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1,151 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "openChatWindow", "resource://gre/modules/MozSocialAPI.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["WorkerAPI"];
|
||||
|
||||
this.WorkerAPI = function WorkerAPI(provider, port) {
|
||||
if (!port)
|
||||
throw new Error("Can't initialize WorkerAPI with a null port");
|
||||
|
||||
this._provider = provider;
|
||||
this._port = port;
|
||||
this._port.onmessage = this._handleMessage.bind(this);
|
||||
|
||||
// Send an "intro" message so the worker knows this is the port
|
||||
// used for the api.
|
||||
// later we might even include an API version - version 0 for now!
|
||||
this._port.postMessage({topic: "social.initialize"});
|
||||
}
|
||||
|
||||
WorkerAPI.prototype = {
|
||||
terminate: function terminate() {
|
||||
this._port.close();
|
||||
},
|
||||
|
||||
_handleMessage: function _handleMessage(event) {
|
||||
let {topic, data} = event.data;
|
||||
let handler = this.handlers[topic];
|
||||
if (!handler) {
|
||||
Cu.reportError("WorkerAPI: topic doesn't have a handler: '" + topic + "'");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
handler.call(this, data);
|
||||
} catch (ex) {
|
||||
Cu.reportError("WorkerAPI: failed to handle message '" + topic + "': " + ex + "\n" + ex.stack);
|
||||
}
|
||||
},
|
||||
|
||||
handlers: {
|
||||
"social.manifest-get": function(data) {
|
||||
// retreive the currently installed manifest from firefox
|
||||
this._port.postMessage({topic: "social.manifest", data: this._provider.manifest});
|
||||
},
|
||||
"social.manifest-set": function(data) {
|
||||
// the provider will get reloaded as a result of this call
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
let origin = this._provider.origin;
|
||||
SocialService.updateProvider(origin, data);
|
||||
},
|
||||
"social.reload-worker": function(data) {
|
||||
this._provider.reload();
|
||||
},
|
||||
"social.user-profile": function (data) {
|
||||
this._provider.updateUserProfile(data);
|
||||
},
|
||||
"social.ambient-notification": function (data) {
|
||||
this._provider.setAmbientNotification(data);
|
||||
},
|
||||
"social.cookies-get": function(data) {
|
||||
// We don't want to trust provider.origin etc, just incase the provider
|
||||
// redirected away or something else bad is going on. So we want to
|
||||
// reach into the Worker's document and fetch the actual cookies it has.
|
||||
// We need to do this via our own message dance.
|
||||
let port = this._port;
|
||||
let whandle = getFrameWorkerHandle(this._provider.workerURL, null);
|
||||
whandle.port.close();
|
||||
whandle._worker.browserPromise.then(browser => {
|
||||
let mm = browser.messageManager;
|
||||
mm.addMessageListener("frameworker:cookie-get-response", function _onCookieResponse(msg) {
|
||||
mm.removeMessageListener("frameworker:cookie-get-response", _onCookieResponse);
|
||||
let cookies = msg.json.split(";");
|
||||
let results = [];
|
||||
cookies.forEach(function(aCookie) {
|
||||
let [name, value] = aCookie.split("=");
|
||||
if (name || value) {
|
||||
results.push({name: unescape(name.trim()),
|
||||
value: value ? unescape(value.trim()) : ""});
|
||||
}
|
||||
});
|
||||
port.postMessage({topic: "social.cookies-get-response",
|
||||
data: results});
|
||||
});
|
||||
mm.sendAsyncMessage("frameworker:cookie-get");
|
||||
});
|
||||
},
|
||||
'social.request-chat': function(data) {
|
||||
openChatWindow(null, this._provider, data);
|
||||
},
|
||||
'social.notification-create': function(data) {
|
||||
if (!Services.prefs.getBoolPref("social.toast-notifications.enabled"))
|
||||
return;
|
||||
|
||||
let port = this._port;
|
||||
let provider = this._provider;
|
||||
let {id, type, icon, body, action, actionArgs} = data;
|
||||
let alertsService = Cc["@mozilla.org/alerts-service;1"]
|
||||
.getService(Ci.nsIAlertsService);
|
||||
function listener(subject, topic, data) {
|
||||
if (topic === "alertclickcallback") {
|
||||
// we always post back the click
|
||||
port.postMessage({topic: "social.notification-action",
|
||||
data: {id: id,
|
||||
action: action,
|
||||
actionArgs: actionArgs}});
|
||||
switch (action) {
|
||||
case "link":
|
||||
// if there is a url, make it open a tab
|
||||
if (actionArgs.toURL) {
|
||||
let uriToOpen = provider.resolveUri(actionArgs.toURL);
|
||||
// Bug 815970 - facebook gives us http:// links even though
|
||||
// the origin is https:// - so we perform a fixup here.
|
||||
let pUri = Services.io.newURI(provider.origin, null, null);
|
||||
if (uriToOpen.scheme != pUri.scheme)
|
||||
uriToOpen.scheme = pUri.scheme;
|
||||
if (provider.isSameOrigin(uriToOpen)) {
|
||||
let xulWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
xulWindow.openUILinkIn(uriToOpen.spec, "tab");
|
||||
} else {
|
||||
Cu.reportError("Not opening notification link " + actionArgs.toURL
|
||||
+ " as not in provider origin");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
alertsService.showAlertNotification(icon,
|
||||
this._provider.name, // title
|
||||
body,
|
||||
!!action, // text clickable if an
|
||||
// action was provided.
|
||||
null,
|
||||
listener,
|
||||
type);
|
||||
},
|
||||
}
|
||||
}
|
@ -7,17 +7,10 @@
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||
|
||||
if CONFIG['MOZ_SOCIAL']:
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||
|
||||
# social is turned off for android
|
||||
EXTRA_JS_MODULES += [
|
||||
'FrameWorker.jsm',
|
||||
'FrameWorkerContent.js',
|
||||
'MessagePortBase.jsm',
|
||||
'MessagePortWorker.js',
|
||||
'MozSocialAPI.jsm',
|
||||
'SocialService.jsm',
|
||||
'WorkerAPI.jsm',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"../../../../../testing/mochitest/browser.eslintrc"
|
||||
]
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
# Note: these tests are disabled if MOZ_SOCIAL is off.
|
||||
|
||||
[DEFAULT]
|
||||
skip-if= buildapp == 'mulet'
|
||||
support-files =
|
||||
head.js
|
||||
data.json
|
||||
echo.sjs
|
||||
worker_xhr.js
|
||||
worker_relative.js
|
||||
relative_import.js
|
||||
worker_social.js
|
||||
worker_eventsource.js
|
||||
eventsource.resource
|
||||
eventsource.resource^headers^
|
||||
|
||||
[browser_workerAPI.js]
|
||||
[browser_SocialProvider.js]
|
||||
[browser_notifications.js]
|
||||
|
||||
# These tests are currently unreliable on ASAN builds with remote frameworkers.
|
||||
[browser_frameworker.js]
|
||||
skip-if = asan || (os == 'linux' && debug) || (os == 'mac' && debug) # Bug 994798 for Linux debug disabling, bug 994300 for Mac debug disabling
|
||||
[browser_frameworker_sandbox.js]
|
||||
skip-if = asan || (os == 'linux' && debug) || (os == 'mac' && debug) # Bug 994798 for Linux debug disabling, bug 994300 for Mac debug disabling
|
@ -1,85 +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/. */
|
||||
|
||||
var provider;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = {
|
||||
origin: 'http://example.com',
|
||||
name: "Example Provider",
|
||||
workerURL: "http://example.com/browser/toolkit/components/social/test/browser/worker_social.js"
|
||||
};
|
||||
|
||||
SocialService.addProvider(manifest, function (p) {
|
||||
provider = p;
|
||||
runTests(tests, undefined, undefined, function () {
|
||||
SocialService.disableProvider(p.origin, function() {
|
||||
ok(!provider.enabled, "removing an enabled provider should have disabled the provider");
|
||||
let port = provider.getWorkerPort();
|
||||
ok(!port, "should not be able to get a port after removing the provider");
|
||||
provider = null;
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testSingleProvider: function(next) {
|
||||
ok(provider.enabled, "provider is initially enabled");
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "should be able to get a port from enabled provider");
|
||||
port.close();
|
||||
ok(provider.workerAPI, "should be able to get a workerAPI from enabled provider");
|
||||
|
||||
provider.enabled = false;
|
||||
|
||||
ok(!provider.enabled, "provider is now disabled");
|
||||
port = provider.getWorkerPort();
|
||||
ok(!port, "shouldn't be able to get a port from disabled provider");
|
||||
ok(!provider.workerAPI, "shouldn't be able to get a workerAPI from disabled provider");
|
||||
|
||||
provider.enabled = true;
|
||||
|
||||
ok(provider.enabled, "provider is re-enabled");
|
||||
port = provider.getWorkerPort();
|
||||
ok(port, "should be able to get a port from re-enabled provider");
|
||||
port.close();
|
||||
ok(provider.workerAPI, "should be able to get a workerAPI from re-enabled provider");
|
||||
next();
|
||||
},
|
||||
testTwoProviders: function(next) {
|
||||
// add another provider, test both workers
|
||||
let manifest = {
|
||||
origin: 'http://test2.example.com',
|
||||
name: "Example Provider 2",
|
||||
workerURL: "http://test2.example.com/browser/toolkit/components/social/test/browser/worker_social.js"
|
||||
};
|
||||
SocialService.addProvider(manifest, function (provider2) {
|
||||
ok(provider.enabled, "provider is initially enabled");
|
||||
ok(provider2.enabled, "provider2 is initially enabled");
|
||||
let port = provider.getWorkerPort();
|
||||
let port2 = provider2.getWorkerPort();
|
||||
ok(port, "have port for provider");
|
||||
ok(port2, "have port for provider2");
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "test-initialization-complete") {
|
||||
ok(true, "first provider initialized");
|
||||
port2.postMessage({topic: "test-initialization"});
|
||||
}
|
||||
}
|
||||
port2.onmessage = function(e) {
|
||||
if (e.data.topic == "test-initialization-complete") {
|
||||
ok(true, "second provider initialized");
|
||||
SocialService.disableProvider(provider2.origin, function() {
|
||||
next();
|
||||
});
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-initialization"});
|
||||
});
|
||||
}
|
||||
}
|
@ -1,389 +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/. */
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// This file tests message ports and semantics of the frameworker which aren't
|
||||
// directly related to the sandbox. See also browser_frameworker_sandbox.js.
|
||||
|
||||
function makeWorkerUrl(runner) {
|
||||
let prefix = "http://example.com/browser/toolkit/components/social/test/browser/echo.sjs?";
|
||||
if (typeof runner == "function") {
|
||||
runner = "var run=" + runner.toSource() + ";run();";
|
||||
}
|
||||
return prefix + encodeURI(runner);
|
||||
}
|
||||
|
||||
var getFrameWorkerHandle;
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/FrameWorker.jsm", scope);
|
||||
getFrameWorkerHandle = scope.getFrameWorkerHandle;
|
||||
|
||||
runTests(tests);
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testSimple: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "ping") {
|
||||
port.postMessage({topic: "pong"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSimple");
|
||||
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "pong") {
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "ping"})
|
||||
},
|
||||
|
||||
// when the client closes early but the worker tries to send anyway...
|
||||
// XXX - disabled due to bug 919878 - we close the frameworker before the
|
||||
// remote browser has completed initializing, leading to failures. Given
|
||||
// this can realistically only happen in this synthesized test environment,
|
||||
// disabling just this test seems OK for now.
|
||||
/***
|
||||
testEarlyClose: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.postMessage({topic: "oh hai"});
|
||||
}
|
||||
}
|
||||
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testEarlyClose");
|
||||
worker.port.close();
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
},
|
||||
***/
|
||||
|
||||
// Check we do get a social.port-closing message as the port is closed.
|
||||
testPortClosingMessage: function(cbnext) {
|
||||
// We use 2 ports - we close the first and report success via the second.
|
||||
let run = function() {
|
||||
let firstPort, secondPort;
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
if (firstPort === undefined) {
|
||||
firstPort = port;
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "social.port-closing") {
|
||||
secondPort.postMessage({topic: "got-closing"});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
secondPort = port;
|
||||
// now both ports are connected we can trigger the client side
|
||||
// closing the first.
|
||||
secondPort.postMessage({topic: "connected"});
|
||||
}
|
||||
}
|
||||
}
|
||||
let workerurl = makeWorkerUrl(run);
|
||||
let worker1 = getFrameWorkerHandle(workerurl, undefined, "testPortClosingMessage worker1");
|
||||
let worker2 = getFrameWorkerHandle(workerurl, undefined, "testPortClosingMessage worker2");
|
||||
worker2.port.onmessage = function(e) {
|
||||
if (e.data.topic == "connected") {
|
||||
// both ports connected, so close the first.
|
||||
worker1.port.close();
|
||||
} else if (e.data.topic == "got-closing") {
|
||||
worker2.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Tests that prototypes added to core objects work with data sent over
|
||||
// the message ports.
|
||||
testPrototypes: function(cbnext) {
|
||||
let run = function() {
|
||||
// Modify the Array prototype...
|
||||
Array.prototype.customfunction = function() {};
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
// Check the data we get via the port has the prototype modification
|
||||
if (e.data.topic == "hello" && e.data.data.customfunction) {
|
||||
port.postMessage({topic: "hello", data: [1,2,3]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// hrmph - this kinda sucks as it is really just testing the actual
|
||||
// implementation rather than the end result, but is OK for now.
|
||||
// Really we are just testing that JSON.parse in the client window
|
||||
// is called.
|
||||
let fakeWindow = {
|
||||
JSON: {
|
||||
parse: function(s) {
|
||||
let data = JSON.parse(s);
|
||||
data.data.somextrafunction = function() {};
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), fakeWindow, "testPrototypes");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "hello") {
|
||||
ok(e.data.data.somextrafunction, "have someextrafunction")
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "hello", data: [1,2,3]});
|
||||
},
|
||||
|
||||
testSameOriginImport: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "ping") {
|
||||
try {
|
||||
importScripts("http://mochi.test:8888/error");
|
||||
} catch(ex) {
|
||||
port.postMessage({topic: "pong", data: ex});
|
||||
return;
|
||||
}
|
||||
port.postMessage({topic: "pong", data: null});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSameOriginImport");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "pong") {
|
||||
isnot(e.data.data, null, "check same-origin applied to importScripts");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "ping"})
|
||||
},
|
||||
|
||||
testRelativeImport: function(cbnext) {
|
||||
let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_relative.js";
|
||||
let worker = getFrameWorkerHandle(url, undefined, "testSameOriginImport");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check relative url in importScripts");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testNavigator: function(cbnext) {
|
||||
let run = function() {
|
||||
let port;
|
||||
ononline = function() {
|
||||
port.postMessage({topic: "ononline", data: navigator.onLine});
|
||||
}
|
||||
onoffline = function() {
|
||||
port.postMessage({topic: "onoffline", data: navigator.onLine});
|
||||
}
|
||||
onconnect = function(e) {
|
||||
port = e.ports[0];
|
||||
port.postMessage({topic: "ready",
|
||||
data: {
|
||||
appName: navigator.appName,
|
||||
appVersion: navigator.appVersion,
|
||||
platform: navigator.platform,
|
||||
userAgent: navigator.userAgent,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
|
||||
let oldManage = ioService.manageOfflineStatus;
|
||||
let oldOffline = ioService.offline;
|
||||
|
||||
ioService.manageOfflineStatus = false;
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testNavigator");
|
||||
let expected_topic = "onoffline";
|
||||
let expected_data = false;
|
||||
worker.port.onmessage = function(e) {
|
||||
is(e.data.topic, "ready");
|
||||
for (let attr of ['appName', 'appVersion', 'platform', 'userAgent']) {
|
||||
// each attribute must be a string with length > 0.
|
||||
is(typeof e.data.data[attr], "string");
|
||||
ok(e.data.data[attr].length > 0);
|
||||
}
|
||||
|
||||
worker.port.onmessage = function(e) {
|
||||
// a handler specifically for the offline notification.
|
||||
is(e.data.topic, "onoffline");
|
||||
is(e.data.data, false);
|
||||
|
||||
// add another handler specifically for the 'online' case.
|
||||
worker.port.onmessage = function(e) {
|
||||
is(e.data.topic, "ononline");
|
||||
is(e.data.data, true);
|
||||
// all good!
|
||||
ioService.manageOfflineStatus = oldManage;
|
||||
ioService.offline = oldOffline;
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
ioService.offline = false;
|
||||
}
|
||||
ioService.offline = true;
|
||||
}
|
||||
},
|
||||
|
||||
testMissingWorker: function(cbnext) {
|
||||
// don't ever create this file! We want a 404.
|
||||
let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_is_missing.js";
|
||||
let worker = getFrameWorkerHandle(url, undefined, "testMissingWorker");
|
||||
Services.obs.addObserver(function handleError(subj, topic, data) {
|
||||
Services.obs.removeObserver(handleError, "social:frameworker-error");
|
||||
is(data, worker._worker.origin, "social:frameworker-error was handled");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}, 'social:frameworker-error', false);
|
||||
worker.port.onmessage = function(e) {
|
||||
ok(false, "social:frameworker-error was handled");
|
||||
cbnext();
|
||||
}
|
||||
},
|
||||
|
||||
testNoConnectWorker: function(cbnext) {
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(function () {}),
|
||||
undefined, "testNoConnectWorker");
|
||||
Services.obs.addObserver(function handleError(subj, topic, data) {
|
||||
Services.obs.removeObserver(handleError, "social:frameworker-error");
|
||||
is(data, worker._worker.origin, "social:frameworker-error was handled");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}, 'social:frameworker-error', false);
|
||||
worker.port.onmessage = function(e) {
|
||||
ok(false, "social:frameworker-error was handled");
|
||||
cbnext();
|
||||
}
|
||||
},
|
||||
|
||||
testEmptyWorker: function(cbnext) {
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(''),
|
||||
undefined, "testEmptyWorker");
|
||||
Services.obs.addObserver(function handleError(subj, topic, data) {
|
||||
Services.obs.removeObserver(handleError, "social:frameworker-error");
|
||||
is(data, worker._worker.origin, "social:frameworker-error was handled");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}, 'social:frameworker-error', false);
|
||||
worker.port.onmessage = function(e) {
|
||||
ok(false, "social:frameworker-error was handled");
|
||||
cbnext();
|
||||
}
|
||||
},
|
||||
|
||||
testWorkerConnectError: function(cbnext) {
|
||||
let run = function () {
|
||||
onconnect = function(e) {
|
||||
throw new Error("worker failure");
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run),
|
||||
undefined, "testWorkerConnectError");
|
||||
Services.obs.addObserver(function handleError(subj, topic, data) {
|
||||
Services.obs.removeObserver(handleError, "social:frameworker-error");
|
||||
is(data, worker._worker.origin, "social:frameworker-error was handled");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}, 'social:frameworker-error', false);
|
||||
worker.port.onmessage = function(e) {
|
||||
ok(false, "social:frameworker-error was handled");
|
||||
cbnext();
|
||||
}
|
||||
},
|
||||
|
||||
// This will create the worker, then send a message to the port, then close
|
||||
// the port - all before the worker has actually initialized.
|
||||
testCloseFirstSend: function(cbnext) {
|
||||
let run = function() {
|
||||
let numPings = 0, numCloses = 0;
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "ping") {
|
||||
numPings += 1;
|
||||
} else if (e.data.topic == "social.port-closing") {
|
||||
numCloses += 1;
|
||||
} else if (e.data.topic == "get-counts") {
|
||||
port.postMessage({topic: "result",
|
||||
result: {ping: numPings, close: numCloses}});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose");
|
||||
worker.port.postMessage({topic: "ping"});
|
||||
worker.port.close();
|
||||
let newPort = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose").port;
|
||||
newPort.onmessage = function(e) {
|
||||
if (e.data.topic == "result") {
|
||||
is(e.data.result.ping, 1, "the worker got the ping");
|
||||
is(e.data.result.close, 1, "the worker got 1 close message");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
newPort.postMessage({topic: "get-counts"});
|
||||
},
|
||||
|
||||
// Like testCloseFirstSend, although in this test the worker has already
|
||||
// initialized (so the "connect pending ports" part of the worker isn't
|
||||
// what needs to handle this case.)
|
||||
testCloseAfterInit: function(cbnext) {
|
||||
let run = function() {
|
||||
let numPings = 0, numCloses = 0;
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "ping") {
|
||||
numPings += 1;
|
||||
} else if (e.data.topic == "social.port-closing") {
|
||||
numCloses += 1;
|
||||
} else if (e.data.topic == "get-counts") {
|
||||
port.postMessage({topic: "result",
|
||||
result: {ping: numPings, close: numCloses}});
|
||||
} else if (e.data.topic == "get-ready") {
|
||||
port.postMessage({topic: "ready"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "ready") {
|
||||
let newPort = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose").port;
|
||||
newPort.postMessage({topic: "ping"});
|
||||
newPort.close();
|
||||
worker.port.postMessage({topic: "get-counts"});
|
||||
} else if (e.data.topic == "result") {
|
||||
is(e.data.result.ping, 1, "the worker got the ping");
|
||||
is(e.data.result.close, 1, "the worker got 1 close message");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "get-ready"});
|
||||
},
|
||||
}
|
@ -1,347 +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/. */
|
||||
|
||||
// This file tests features made available to the frameworker via the sandbox.
|
||||
// For other frameworker tests, see browser_frameworker.js
|
||||
|
||||
function makeWorkerUrl(runner) {
|
||||
let prefix = "http://example.com/browser/toolkit/components/social/test/browser/echo.sjs?";
|
||||
if (typeof runner == "function") {
|
||||
runner = "var run=" + runner.toSource() + ";run();";
|
||||
}
|
||||
return prefix + encodeURI(runner);
|
||||
}
|
||||
|
||||
var getFrameWorkerHandle;
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/FrameWorker.jsm", scope);
|
||||
getFrameWorkerHandle = scope.getFrameWorkerHandle;
|
||||
|
||||
runTests(tests);
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testArrayUsingBuffer: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "go") {
|
||||
let buffer = new ArrayBuffer(10);
|
||||
// this one has always worked in the past, but worth checking anyway...
|
||||
if (new Uint8Array(buffer).length != 10) {
|
||||
port.postMessage({topic: "result", reason: "first length was not 10"});
|
||||
return;
|
||||
}
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
if (new Uint8Array(buffer).length != 10) {
|
||||
port.postMessage({topic: "result", reason: "length in onload handler was not 10"});
|
||||
return;
|
||||
}
|
||||
// all seems good!
|
||||
port.postMessage({topic: "result", reason: "ok"});
|
||||
}
|
||||
let blob = new Blob([buffer], {type: "binary"});
|
||||
reader.readAsArrayBuffer(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testArray");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "result") {
|
||||
is(e.data.reason, "ok", "check the array worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "go"});
|
||||
},
|
||||
|
||||
testArrayUsingReader: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "go") {
|
||||
let buffer = new ArrayBuffer(10);
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
try {
|
||||
if (new Uint8Array(reader.result).length != 10) {
|
||||
port.postMessage({topic: "result", reason: "length in onload handler was not 10"});
|
||||
return;
|
||||
}
|
||||
// all seems good!
|
||||
port.postMessage({topic: "result", reason: "ok"});
|
||||
} catch (ex) {
|
||||
port.postMessage({topic: "result", reason: ex.toString()});
|
||||
}
|
||||
}
|
||||
let blob = new Blob([buffer], {type: "binary"});
|
||||
reader.readAsArrayBuffer(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testArray");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "result") {
|
||||
is(e.data.reason, "ok", "check the array worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "go"});
|
||||
},
|
||||
|
||||
testXHR: function(cbnext) {
|
||||
// NOTE: this url MUST be in the same origin as worker_xhr.js fetches from!
|
||||
let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_xhr.js";
|
||||
let worker = getFrameWorkerHandle(url, undefined, "testXHR");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check the xhr test worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testLocalStorage: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
try {
|
||||
localStorage.setItem("foo", "1");
|
||||
} catch(e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to set localStorage, " + e.toString() });
|
||||
return;
|
||||
}
|
||||
|
||||
var ok;
|
||||
try {
|
||||
ok = localStorage["foo"] == 1;
|
||||
} catch (e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to read localStorage, " + e.toString() });
|
||||
return;
|
||||
}
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testLocalStorage", null, true);
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check the localStorage test worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testNoLocalStorage: function(cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
try {
|
||||
localStorage.setItem("foo", "1");
|
||||
} catch(e) {
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
return;
|
||||
}
|
||||
|
||||
port.postMessage({topic: "done", result: "FAILED because localStorage was exposed" });
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testNoLocalStorage");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check that retrieving localStorage fails by default");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testBase64: function (cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
var ok = false;
|
||||
try {
|
||||
ok = btoa("1234") == "MTIzNA==";
|
||||
} catch(e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to call btoa, " + e.toString() });
|
||||
return;
|
||||
}
|
||||
if (!ok) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling btoa"});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ok = atob("NDMyMQ==") == "4321";
|
||||
} catch (e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to call atob, " + e.toString() });
|
||||
return;
|
||||
}
|
||||
if (!ok) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling atob"});
|
||||
return;
|
||||
}
|
||||
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testBase64");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check the atob/btoa test worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testTimeouts: function (cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
|
||||
var timeout;
|
||||
try {
|
||||
timeout = setTimeout(function () {
|
||||
port.postMessage({topic: "done", result: "FAILED cancelled timeout was called"});
|
||||
}, 100);
|
||||
} catch (ex) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling setTimeout: " + ex});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
clearTimeout(timeout);
|
||||
} catch (ex) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling clearTimeout: " + ex});
|
||||
return;
|
||||
}
|
||||
|
||||
var counter = 0;
|
||||
try {
|
||||
timeout = setInterval(function () {
|
||||
if (++counter == 2) {
|
||||
clearInterval(timeout);
|
||||
setTimeout(function () {
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
return;
|
||||
}, 0);
|
||||
}
|
||||
}, 100);
|
||||
} catch (ex) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling setInterval: " + ex});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testTimeouts");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check that timeouts worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testWebSocket: function (cbnext) {
|
||||
let run = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
|
||||
try {
|
||||
var exampleSocket = new WebSocket("ws://mochi.test:8888/socketserver");
|
||||
} catch (e) {
|
||||
port.postMessage({topic: "done", result: "FAILED calling WebSocket constructor: " + e});
|
||||
return;
|
||||
}
|
||||
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
}
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testWebSocket");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "done") {
|
||||
is(e.data.result, "ok", "check that websockets worked");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testEventSource: function(cbnext) {
|
||||
let worker = getFrameWorkerHandle("https://example.com/browser/toolkit/components/social/test/browser/worker_eventsource.js", undefined, "testEventSource");
|
||||
worker.port.onmessage = function(e) {
|
||||
let m = e.data;
|
||||
if (m.topic == "eventSourceTest") {
|
||||
if (m.result.ok != undefined)
|
||||
ok(m.result.ok, e.data.result.msg);
|
||||
if (m.result.is != undefined)
|
||||
is(m.result.is, m.result.match, m.result.msg);
|
||||
if (m.result.info != undefined)
|
||||
info(m.result.info);
|
||||
} else if (e.data.topic == "pong") {
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "ping"})
|
||||
},
|
||||
|
||||
testIndexedDB: function(cbnext) {
|
||||
let worker = getFrameWorkerHandle("https://example.com/browser/toolkit/components/social/test/browser/worker_social.js", undefined, "testIndexedDB");
|
||||
worker.port.onmessage = function(e) {
|
||||
let m = e.data;
|
||||
if (m.topic == "social.indexeddb-result") {
|
||||
is(m.data.result, "ok", "created indexeddb");
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "test-indexeddb-create"})
|
||||
},
|
||||
|
||||
testSubworker: function(cbnext) {
|
||||
// the main "frameworker"...
|
||||
let mainworker = function() {
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "go") {
|
||||
let suburl = e.data.data;
|
||||
let worker = new Worker(suburl);
|
||||
worker.onmessage = function(sube) {
|
||||
port.postMessage({topic: "sub-message", data: sube.data});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The "subworker" that is actually a real, bona-fide worker.
|
||||
let subworker = function() {
|
||||
postMessage("hello");
|
||||
}
|
||||
let worker = getFrameWorkerHandle(makeWorkerUrl(mainworker), undefined, "testSubWorker");
|
||||
worker.port.onmessage = function(e) {
|
||||
if (e.data.topic == "sub-message" && e.data.data == "hello") {
|
||||
worker.terminate();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
worker.port.postMessage({topic: "go", data: makeWorkerUrl(subworker)});
|
||||
}
|
||||
}
|
@ -1,87 +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/. */
|
||||
|
||||
const TEST_PROVIDER_ORIGIN = 'http://example.com';
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function ensureProvider(workerFunction, cb) {
|
||||
let manifest = {
|
||||
origin: TEST_PROVIDER_ORIGIN,
|
||||
name: "Example Provider",
|
||||
workerURL: "http://example.com/browser/toolkit/components/social/test/browser/echo.sjs?"
|
||||
+ encodeURI("let run=" + workerFunction.toSource()) + ";run();"
|
||||
};
|
||||
|
||||
SocialService.addProvider(manifest, function (p) {
|
||||
cb(p);
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let cbPostTest = function(cb) {
|
||||
SocialService.disableProvider(TEST_PROVIDER_ORIGIN, function() {cb()});
|
||||
};
|
||||
replaceAlertsService();
|
||||
registerCleanupFunction(restoreAlertsService);
|
||||
runTests(tests, undefined, cbPostTest);
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testNotificationCallback: function(cbnext) {
|
||||
let run = function() {
|
||||
let testPort, apiPort;
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "social.initialize") { // this is the api port.
|
||||
apiPort = port;
|
||||
} else if (e.data.topic == "test.initialize") { // test suite port.
|
||||
testPort = port;
|
||||
apiPort.postMessage({topic: 'social.notification-create',
|
||||
data: {
|
||||
id: "the id",
|
||||
body: 'test notification',
|
||||
action: 'callback',
|
||||
actionArgs: { data: "something" }
|
||||
}
|
||||
});
|
||||
} else if (e.data.topic == "social.notification-action") {
|
||||
let data = e.data.data;
|
||||
let ok = data && data.action == "callback" &&
|
||||
data.actionArgs && e.data.data.actionArgs.data == "something";
|
||||
testPort.postMessage({topic: "test.done", data: ok});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ensureProvider(run, function(provider) {
|
||||
let observer = {
|
||||
observedData: null,
|
||||
observe: function(subject, topic, data) {
|
||||
this.observedData = JSON.parse(data);
|
||||
Services.obs.removeObserver(observer, "social-test:notification-alert");
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(observer, "social-test:notification-alert", false);
|
||||
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "got port from worker");
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "test.done") {
|
||||
ok(e.data.data, "check the test worked");
|
||||
ok(observer.observedData, "test observer fired");
|
||||
is(observer.observedData.text, "test notification", "check the alert text is correct");
|
||||
is(observer.observedData.title, "Example Provider", "check the alert title is correct");
|
||||
is(observer.observedData.textClickable, true, "check the alert is clickable");
|
||||
port.close();
|
||||
cbnext();
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test.initialize"});
|
||||
});
|
||||
}
|
||||
};
|
@ -1,224 +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/. */
|
||||
|
||||
var provider;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
replaceAlertsService();
|
||||
registerCleanupFunction(restoreAlertsService);
|
||||
|
||||
let manifest = {
|
||||
origin: 'http://example.com',
|
||||
name: "Example Provider",
|
||||
workerURL: "http://example.com/browser/toolkit/components/social/test/browser/worker_social.js"
|
||||
};
|
||||
|
||||
SocialService.addProvider(manifest, function (p) {
|
||||
// toolkit does not enable providers by default, that is handled in the
|
||||
// browser, we need to enable it in our tests.
|
||||
p.enabled = true;
|
||||
provider = p;
|
||||
runTests(tests, undefined, undefined, function () {
|
||||
SocialService.disableProvider(provider.origin, finish);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testProfile: function(next) {
|
||||
let expect = {
|
||||
portrait: "https://example.com/portrait.jpg",
|
||||
userName: "trickster",
|
||||
displayName: "Kuma Lisa",
|
||||
profileURL: "http://en.wikipedia.org/wiki/Kuma_Lisa"
|
||||
}
|
||||
function ob(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(ob, "social:profile-changed");
|
||||
is(aData, provider.origin, "update of profile from our provider");
|
||||
let profile = provider.profile;
|
||||
is(profile.portrait, expect.portrait, "portrait is set");
|
||||
is(profile.userName, expect.userName, "userName is set");
|
||||
is(profile.displayName, expect.displayName, "displayName is set");
|
||||
is(profile.profileURL, expect.profileURL, "profileURL is set");
|
||||
next();
|
||||
}
|
||||
Services.obs.addObserver(ob, "social:profile-changed", false);
|
||||
let port = provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-profile", data: expect});
|
||||
port.close();
|
||||
},
|
||||
|
||||
testAmbientNotification: function(next) {
|
||||
let expect = {
|
||||
name: "test-ambient"
|
||||
}
|
||||
function ob(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(ob, "social:ambient-notification-changed");
|
||||
is(aData, provider.origin, "update is from our provider");
|
||||
let notif = provider.ambientNotificationIcons[expect.name];
|
||||
is(notif.name, expect.name, "ambientNotification reflected");
|
||||
|
||||
next();
|
||||
}
|
||||
Services.obs.addObserver(ob, "social:ambient-notification-changed", false);
|
||||
let port = provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-ambient", data: expect});
|
||||
port.close();
|
||||
},
|
||||
|
||||
testProfileCleared: function(next) {
|
||||
let sent = {
|
||||
userName: ""
|
||||
};
|
||||
function ob(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(ob, "social:profile-changed");
|
||||
is(aData, provider.origin, "update of profile from our provider");
|
||||
is(Object.keys(provider.profile).length, 0, "profile was cleared by empty username");
|
||||
is(Object.keys(provider.ambientNotificationIcons).length, 0, "icons were cleared by empty username");
|
||||
|
||||
next();
|
||||
}
|
||||
Services.obs.addObserver(ob, "social:profile-changed", false);
|
||||
provider.workerAPI._port.postMessage({topic: "test-profile", data: sent});
|
||||
},
|
||||
|
||||
testNoCookies: function(next) {
|
||||
// use a big, blunt stick to remove cookies.
|
||||
Services.cookies.removeAll();
|
||||
let port = provider.getWorkerPort();
|
||||
port.onmessage = function onMessage(event) {
|
||||
let {topic, data} = event.data;
|
||||
if (topic == "test.cookies-get-response") {
|
||||
is(data.length, 0, "got no cookies");
|
||||
port.close();
|
||||
next();
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-initialization"});
|
||||
port.postMessage({topic: "test.cookies-get"});
|
||||
},
|
||||
|
||||
testCookies: function(next) {
|
||||
let port = provider.getWorkerPort();
|
||||
port.onmessage = function onMessage(event) {
|
||||
let {topic, data} = event.data;
|
||||
if (topic == "test.cookies-get-response") {
|
||||
is(data.length, 2, "got 2 cookies");
|
||||
is(data[0].name, "cheez", "cookie has the correct name");
|
||||
is(data[0].value, "burger", "cookie has the correct value");
|
||||
is(data[1].name, "moar", "cookie has the correct name");
|
||||
is(data[1].value, "bacon", "cookie has the correct value");
|
||||
Services.cookies.remove('.example.com', '/', 'cheez', {}, false);
|
||||
Services.cookies.remove('.example.com', '/', 'moar', {}, false);
|
||||
port.close();
|
||||
next();
|
||||
}
|
||||
}
|
||||
var MAX_EXPIRY = Math.pow(2, 62);
|
||||
Services.cookies.add('.example.com', '/', 'cheez', 'burger', false, false, true, MAX_EXPIRY);
|
||||
Services.cookies.add('.example.com', '/', 'moar', 'bacon', false, false, true, MAX_EXPIRY);
|
||||
port.postMessage({topic: "test-initialization"});
|
||||
port.postMessage({topic: "test.cookies-get"});
|
||||
},
|
||||
|
||||
testWorkerReload: function(next) {
|
||||
let fw = {};
|
||||
Cu.import("resource://gre/modules/FrameWorker.jsm", fw);
|
||||
|
||||
let worker = fw.getFrameWorkerHandle(provider.workerURL, undefined, "testWorkerReload");
|
||||
let port = provider.getWorkerPort();
|
||||
// this observer will be fired when the worker reloads - it ensures the
|
||||
// old port was closed and the new worker is functioning.
|
||||
Services.obs.addObserver(function reloadObserver() {
|
||||
Services.obs.removeObserver(reloadObserver, "social:provider-reload");
|
||||
ok(port._closed, "old port was closed by the reload");
|
||||
let newWorker = fw.getFrameWorkerHandle(provider.workerURL, undefined, "testWorkerReload - worker2");
|
||||
let newPort = provider.getWorkerPort();
|
||||
newPort.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-initialization-complete":
|
||||
// and we are done.
|
||||
newPort.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
newPort.postMessage({topic: "test-initialization"});
|
||||
}, "social:provider-reload", false);
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-initialization-complete":
|
||||
// tell the worker to send the reload msg - that will trigger the
|
||||
// frameworker to unload and for our content script's unload
|
||||
// handler to post a "test-result" message.
|
||||
port.postMessage({topic: "test-reload-init"});
|
||||
// and the "social:provider-reload" observer should fire...
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-initialization"});
|
||||
},
|
||||
|
||||
testNotificationLinks: function(next) {
|
||||
let port = provider.getWorkerPort();
|
||||
let data = {
|
||||
id: 'an id',
|
||||
body: 'the text',
|
||||
action: 'link',
|
||||
actionArgs: {} // will get a toURL elt during the tests...
|
||||
}
|
||||
let testArgs = [
|
||||
// toURL, expectedLocation, expectedWhere]
|
||||
["http://example.com", "http://example.com/", "tab"],
|
||||
// bug 815970 - test that a mis-matched scheme gets patched up.
|
||||
["https://example.com", "http://example.com/", "tab"],
|
||||
// check an off-origin link is not opened.
|
||||
["https://mochitest:8888/", null, null]
|
||||
];
|
||||
|
||||
// we monkey-patch openUILinkIn
|
||||
let oldopenUILinkIn = window.openUILinkIn;
|
||||
registerCleanupFunction(function () {
|
||||
// restore the monkey-patch
|
||||
window.openUILinkIn = oldopenUILinkIn;
|
||||
});
|
||||
let openLocation;
|
||||
let openWhere;
|
||||
window.openUILinkIn = function(location, where) {
|
||||
openLocation = location;
|
||||
openWhere = where;
|
||||
}
|
||||
|
||||
// the testing framework.
|
||||
let toURL, expectedLocation, expectedWhere;
|
||||
function nextTest() {
|
||||
if (testArgs.length == 0) {
|
||||
port.close();
|
||||
next(); // all out of tests!
|
||||
return;
|
||||
}
|
||||
openLocation = openWhere = null;
|
||||
[toURL, expectedLocation, expectedWhere] = testArgs.shift();
|
||||
data.actionArgs.toURL = toURL;
|
||||
port.postMessage({topic: 'test-notification-create', data: data});
|
||||
}
|
||||
|
||||
port.onmessage = function(evt) {
|
||||
if (evt.data.topic == "did-notification-create") {
|
||||
is(openLocation, expectedLocation, "url actually opened was " + openLocation);
|
||||
is(openWhere, expectedWhere, "the url was opened in a " + expectedWhere);
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
// and kick off the tests.
|
||||
port.postMessage({topic: "test-initialization"});
|
||||
nextTest();
|
||||
},
|
||||
|
||||
};
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"response": "ok"
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// A server-side JS test file for frameworker testing. It exists only to
|
||||
// work-around a lack of data: URL support in the frameworker.
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// The query string is the javascript - we just write it back.
|
||||
response.setHeader("Content-Type", "application/javascript; charset=utf-8", false);
|
||||
response.write(unescape(request.queryString));
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
:this file must be enconded in utf8
|
||||
:and its Content-Type must be equal to text/event-stream
|
||||
|
||||
retry:10
|
||||
data: 1
|
||||
event: test-message
|
||||
|
||||
retry:10
|
||||
data: 1
|
||||
|
||||
retry:10
|
||||
data: 1
|
@ -1,2 +0,0 @@
|
||||
Content-Type: text/event-stream
|
||||
Cache-Control: no-cache, must-revalidate
|
@ -1,107 +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/. */
|
||||
|
||||
var SocialService = Components.utils.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
var MockRegistrar = Components.utils.import("resource://testing-common/MockRegistrar.jsm", {}).MockRegistrar;
|
||||
|
||||
// A helper to run a suite of tests.
|
||||
// The "test object" should be an object with function names as keys and a
|
||||
// function as the value. The functions will be called with a "cbnext" param
|
||||
// which should be called when the test is complete.
|
||||
// eg:
|
||||
// test = {
|
||||
// foo: function(cbnext) {... cbnext();}
|
||||
// }
|
||||
function runTests(tests, cbPreTest, cbPostTest, cbFinish) {
|
||||
let testIter = (function*() {
|
||||
for (let name in tests) {
|
||||
if (tests.hasOwnProperty(name)) {
|
||||
yield [name, tests[name]];
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
if (cbPreTest === undefined) {
|
||||
cbPreTest = function(cb) {cb()};
|
||||
}
|
||||
if (cbPostTest === undefined) {
|
||||
cbPostTest = function(cb) {cb()};
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
let result = testIter.next();
|
||||
if (result.done) {
|
||||
// out of items:
|
||||
(cbFinish || finish)();
|
||||
return;
|
||||
}
|
||||
let [name, func] = result.value;
|
||||
// We run on a timeout as the frameworker also makes use of timeouts, so
|
||||
// this helps keep the debug messages sane.
|
||||
executeSoon(function() {
|
||||
function cleanupAndRunNextTest() {
|
||||
info("sub-test " + name + " complete");
|
||||
cbPostTest(runNextTest);
|
||||
}
|
||||
cbPreTest(function() {
|
||||
info("sub-test " + name + " starting");
|
||||
try {
|
||||
func.call(tests, cleanupAndRunNextTest);
|
||||
} catch (ex) {
|
||||
ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
|
||||
cleanupAndRunNextTest();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
runNextTest();
|
||||
}
|
||||
|
||||
// A mock notifications server. Based on:
|
||||
// dom/tests/mochitest/notification/notification_common.js
|
||||
|
||||
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
||||
|
||||
function MockAlertsService() {}
|
||||
|
||||
MockAlertsService.prototype = {
|
||||
|
||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name) {
|
||||
let obData = JSON.stringify({
|
||||
imageUrl: imageUrl,
|
||||
title: title,
|
||||
text:text,
|
||||
textClickable: textClickable,
|
||||
cookie: cookie,
|
||||
name: name
|
||||
});
|
||||
Services.obs.notifyObservers(null, "social-test:notification-alert", obData);
|
||||
|
||||
if (textClickable) {
|
||||
// probably should do this async....
|
||||
alertListener.observe(null, "alertclickcallback", cookie);
|
||||
}
|
||||
|
||||
alertListener.observe(null, "alertfinished", cookie);
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.nsISupports) ||
|
||||
aIID.equals(Ci.nsIAlertsService))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
var originalAlertsServiceCID;
|
||||
function replaceAlertsService() {
|
||||
originalAlertsServiceCID =
|
||||
MockRegistrar.register(ALERTS_SERVICE_CONTRACT_ID, MockAlertsService);
|
||||
}
|
||||
|
||||
function restoreAlertsService() {
|
||||
MockRegistrar.unregister(originalAlertsServiceCID);
|
||||
}
|
||||
// end of alerts service mock.
|
@ -1,9 +0,0 @@
|
||||
dump("relative_import file\n");
|
||||
|
||||
// Please keep 'causeError' on line 4; we test the error location.
|
||||
function causeError() { does_not_exist(); }
|
||||
|
||||
testVar = "oh hai";
|
||||
function testFunc() {
|
||||
return "oh hai";
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
var port, es;
|
||||
|
||||
var url = "https://example.com/browser/toolkit/components/social/test/browser/eventsource.resource";
|
||||
|
||||
function ok(a, msg) {
|
||||
port.postMessage({topic: "eventSourceTest",
|
||||
result: {ok: a, msg: msg}});
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
port.postMessage({topic: "eventSourceTest",
|
||||
result: {is: a, match: b, msg: msg}});
|
||||
}
|
||||
|
||||
function esListener(e) {
|
||||
esListener.msg_ok = true;
|
||||
}
|
||||
|
||||
function esOnmessage(e) {
|
||||
ok(true, "onmessage test");
|
||||
ok(esListener.msg_ok, "listener test");
|
||||
es.close();
|
||||
port.postMessage({topic: "pong"});
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
try {
|
||||
es = new EventSource(url);
|
||||
is(es.url, url, "eventsource.resource accessed", "we can create an eventsource instance");
|
||||
es.addEventListener('test-message', esListener, true);
|
||||
es.onmessage = esOnmessage;
|
||||
} catch (e) {}
|
||||
ok(!!es, "we can create an eventsource instance");
|
||||
}
|
||||
|
||||
onconnect = function(e) {
|
||||
port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
if (e.data.topic == "ping") {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// Used to test XHR in the worker.
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
let req;
|
||||
try {
|
||||
importScripts("relative_import.js");
|
||||
// the import should have exposed "testVar" and "testFunc" from the module.
|
||||
if (testVar != "oh hai" || testFunc() != "oh hai") {
|
||||
port.postMessage({topic: "done", result: "import worked but global is not available"});
|
||||
return;
|
||||
}
|
||||
|
||||
// causeError will cause a script error, so that we can check the
|
||||
// error location for importScripts'ed files is correct.
|
||||
try {
|
||||
causeError();
|
||||
} catch(e) {
|
||||
let fileName = e.fileName;
|
||||
if (fileName.startsWith("http") &&
|
||||
fileName.endsWith("/relative_import.js") &&
|
||||
e.lineNumber == 4)
|
||||
port.postMessage({topic: "done", result: "ok"});
|
||||
else
|
||||
port.postMessage({topic: "done", result: "invalid error location: " + fileName + ":" + e.lineNumber});
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to importScripts, " + e.toString() });
|
||||
return;
|
||||
}
|
||||
port.postMessage({topic: "done", result: "FAILED to importScripts, no exception" });
|
||||
}
|
@ -1,59 +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/. */
|
||||
|
||||
// apiPort is our port to WorkerAPI
|
||||
var apiPort;
|
||||
// testerPort is whatever port a test calls us on
|
||||
var testerPort;
|
||||
|
||||
onconnect = function(e) {
|
||||
// assume this is a test connecting, but if we get
|
||||
// social.initialize, we know it is our WorkerAPI
|
||||
// instance connecting and we'll set apiPort
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function onMessage(event) {
|
||||
let {topic, data} = event.data;
|
||||
switch (topic) {
|
||||
case "social.initialize":
|
||||
apiPort = port;
|
||||
break;
|
||||
case "test-initialization":
|
||||
testerPort = port;
|
||||
port.postMessage({topic: "test-initialization-complete"});
|
||||
break;
|
||||
case "test-profile":
|
||||
apiPort.postMessage({topic: "social.user-profile", data: data});
|
||||
break;
|
||||
case "test-ambient":
|
||||
apiPort.postMessage({topic: "social.ambient-notification", data: data});
|
||||
break;
|
||||
case "test.cookies-get":
|
||||
apiPort.postMessage({topic: "social.cookies-get"});
|
||||
break;
|
||||
case "social.cookies-get-response":
|
||||
testerPort.postMessage({topic: "test.cookies-get-response", data: data});
|
||||
break;
|
||||
case "test-reload-init":
|
||||
apiPort.postMessage({topic: 'social.reload-worker'});
|
||||
break;
|
||||
case "test-notification-create":
|
||||
apiPort.postMessage({topic: 'social.notification-create',
|
||||
data: data});
|
||||
testerPort.postMessage({topic: 'did-notification-create'});
|
||||
break;
|
||||
case "test-indexeddb-create":
|
||||
var request = indexedDB.open("workerdb", 1);
|
||||
request.onerror = function(event) {
|
||||
port.postMessage({topic: 'social.indexeddb-result', data: { result: "error" }});
|
||||
};
|
||||
request.onsuccess = function(event) {
|
||||
// Do something with request.result!
|
||||
var db = request.result;
|
||||
db.close();
|
||||
port.postMessage({topic: 'social.indexeddb-result', data: { result: "ok" }});
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// Used to test XHR in the worker.
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
let req;
|
||||
try {
|
||||
req = new XMLHttpRequest();
|
||||
} catch(e) {
|
||||
port.postMessage({topic: "done", result: "FAILED to create XHR object, " + e.toString() });
|
||||
}
|
||||
if (req === undefined) { // until bug 756173 is fixed...
|
||||
port.postMessage({topic: "done", result: "FAILED to create XHR object"});
|
||||
return;
|
||||
}
|
||||
// The test that uses this worker MUST use the same origin to load the worker.
|
||||
// We fetch the test app manifest so we can check the data is what we expect.
|
||||
let url = "https://example.com/browser/toolkit/components/social/test/browser/data.json";
|
||||
req.open("GET", url, true);
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState === 4) {
|
||||
let ok = req.status == 200 && req.responseText.length > 0;
|
||||
if (ok) {
|
||||
// check we actually got something sane...
|
||||
try {
|
||||
let data = JSON.parse(req.responseText);
|
||||
ok = "response" in data;
|
||||
} catch(e) {
|
||||
ok = e.toString();
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "done", result: ok ? "ok" : "bad response"});
|
||||
}
|
||||
}
|
||||
req.send(null);
|
||||
}
|
Loading…
Reference in New Issue
Block a user