570 lines
17 KiB
JavaScript
570 lines
17 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/**
|
|
* Check the basic behavior of on/off.
|
|
*/
|
|
add_task(async function test_add_remove_event_listener() {
|
|
const tab = await addTab("https://example.com/document-builder.sjs?html=tab");
|
|
const browsingContext = tab.linkedBrowser.browsingContext;
|
|
const contextDescriptor = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext.browserId,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
info("Add an listener for eventemitter.testEvent");
|
|
const events = [];
|
|
const onEvent = (event, data) => events.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 1);
|
|
|
|
info(
|
|
"Remove a listener for a callback not added before and check that the first one is still registered"
|
|
);
|
|
const anotherCallback = () => {};
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
anotherCallback
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 2);
|
|
|
|
info("Remove the listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 2);
|
|
|
|
info("Add the listener for eventemitter.testEvent again");
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 3);
|
|
|
|
info("Remove the listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
info("Remove the listener again to check the API will not throw");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function test_add_remove_event_listener_for_user_context() {
|
|
const tab = await addTab("https://example.com/document-builder.sjs?html=tab");
|
|
const browsingContext = tab.linkedBrowser.browsingContext;
|
|
const contextDescriptor = {
|
|
type: ContextDescriptorType.UserContext,
|
|
id: browsingContext.originAttributes.userContextId,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
info("Add an listener for eventemitter.testEvent");
|
|
const events = [];
|
|
const onEvent = (event, data) => events.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 1);
|
|
|
|
info("Remove the listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function test_has_listener() {
|
|
const tab1 = await addTab("https://example.com/document-builder.sjs?html=1");
|
|
const browsingContext1 = tab1.linkedBrowser.browsingContext;
|
|
|
|
const tab2 = await addTab("https://example.com/document-builder.sjs?html=2");
|
|
const browsingContext2 = tab2.linkedBrowser.browsingContext;
|
|
|
|
const contextDescriptor1 = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext1.browserId,
|
|
};
|
|
const contextDescriptor2 = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext2.browserId,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
|
|
// Shortcut for the EventsDispatcher.hasListener API.
|
|
function hasListener(contextId) {
|
|
return root.eventsDispatcher.hasListener("eventemitter.testEvent", {
|
|
contextId,
|
|
});
|
|
}
|
|
|
|
const onEvent = () => {};
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor1,
|
|
onEvent
|
|
);
|
|
ok(hasListener(browsingContext1.id), "Has a listener for browsingContext1");
|
|
ok(!hasListener(browsingContext2.id), "No listener for browsingContext2");
|
|
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor2,
|
|
onEvent
|
|
);
|
|
ok(hasListener(browsingContext1.id), "Still a listener for browsingContext1");
|
|
ok(hasListener(browsingContext2.id), "Has a listener for browsingContext2");
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor1,
|
|
onEvent
|
|
);
|
|
ok(!hasListener(browsingContext1.id), "No listener for browsingContext1");
|
|
ok(hasListener(browsingContext2.id), "Still a listener for browsingContext2");
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor2,
|
|
onEvent
|
|
);
|
|
ok(!hasListener(browsingContext1.id), "No listener for browsingContext1");
|
|
ok(!hasListener(browsingContext2.id), "No listener for browsingContext2");
|
|
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
{
|
|
type: ContextDescriptorType.All,
|
|
},
|
|
onEvent
|
|
);
|
|
ok(hasListener(browsingContext1.id), "Has a listener for browsingContext1");
|
|
ok(hasListener(browsingContext2.id), "Has a listener for browsingContext2");
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
{
|
|
type: ContextDescriptorType.All,
|
|
},
|
|
onEvent
|
|
);
|
|
ok(!hasListener(browsingContext1.id), "No listener for browsingContext1");
|
|
ok(!hasListener(browsingContext2.id), "No listener for browsingContext2");
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab2);
|
|
gBrowser.removeTab(tab1);
|
|
});
|
|
|
|
/**
|
|
* Check that two callbacks can subscribe to the same event in the same context
|
|
* in parallel.
|
|
*/
|
|
add_task(async function test_two_callbacks() {
|
|
const tab = await addTab("https://example.com/document-builder.sjs?html=tab");
|
|
const browsingContext = tab.linkedBrowser.browsingContext;
|
|
const contextDescriptor = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext.browserId,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
|
|
info("Add an listener for eventemitter.testEvent");
|
|
const events = [];
|
|
const onEvent = (event, data) => events.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 1);
|
|
|
|
info("Add another listener for eventemitter.testEvent");
|
|
const otherevents = [];
|
|
const otherCallback = (event, data) => otherevents.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
otherCallback
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 2);
|
|
is(otherevents.length, 1);
|
|
|
|
info("Remove the other listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
otherCallback
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 3);
|
|
is(otherevents.length, 1);
|
|
|
|
info("Remove the first listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 3);
|
|
is(otherevents.length, 1);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab);
|
|
});
|
|
|
|
/**
|
|
* Check that two callbacks can subscribe to the same event in the two contexts.
|
|
*/
|
|
add_task(async function test_two_contexts() {
|
|
const tab1 = await addTab("https://example.com/document-builder.sjs?html=1");
|
|
const browsingContext1 = tab1.linkedBrowser.browsingContext;
|
|
|
|
const tab2 = await addTab("https://example.com/document-builder.sjs?html=2");
|
|
const browsingContext2 = tab2.linkedBrowser.browsingContext;
|
|
|
|
const contextDescriptor1 = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext1.browserId,
|
|
};
|
|
const contextDescriptor2 = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext2.browserId,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
|
|
const events1 = [];
|
|
const onEvent1 = (event, data) => events1.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor1,
|
|
onEvent1
|
|
);
|
|
is(await isSubscribed(root, browsingContext1), true);
|
|
is(await isSubscribed(root, browsingContext2), false);
|
|
|
|
const events2 = [];
|
|
const onEvent2 = (event, data) => events2.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor2,
|
|
onEvent2
|
|
);
|
|
is(await isSubscribed(root, browsingContext1), true);
|
|
is(await isSubscribed(root, browsingContext2), true);
|
|
|
|
await emitTestEvent(root, browsingContext1, monitoringEvents);
|
|
is(events1.length, 1);
|
|
is(events2.length, 0);
|
|
|
|
await emitTestEvent(root, browsingContext2, monitoringEvents);
|
|
is(events1.length, 1);
|
|
is(events2.length, 1);
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor1,
|
|
onEvent1
|
|
);
|
|
is(await isSubscribed(root, browsingContext1), false);
|
|
is(await isSubscribed(root, browsingContext2), true);
|
|
|
|
// No event expected here since the module for browsingContext1 is no longer
|
|
// subscribed
|
|
await emitTestEvent(root, browsingContext1, monitoringEvents);
|
|
is(events1.length, 1);
|
|
is(events2.length, 1);
|
|
|
|
// Whereas the module for browsingContext2 is still subscribed
|
|
await emitTestEvent(root, browsingContext2, monitoringEvents);
|
|
is(events1.length, 1);
|
|
is(events2.length, 2);
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor2,
|
|
onEvent2
|
|
);
|
|
is(await isSubscribed(root, browsingContext1), false);
|
|
is(await isSubscribed(root, browsingContext2), false);
|
|
|
|
await emitTestEvent(root, browsingContext1, monitoringEvents);
|
|
await emitTestEvent(root, browsingContext2, monitoringEvents);
|
|
is(events1.length, 1);
|
|
is(events2.length, 2);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab2);
|
|
gBrowser.removeTab(tab1);
|
|
});
|
|
|
|
/**
|
|
* Check that adding and removing first listener for the specific context and then
|
|
* for the global context works as expected.
|
|
*/
|
|
add_task(
|
|
async function test_remove_context_event_listener_and_then_global_event_listener() {
|
|
const tab = await addTab(
|
|
"https://example.com/document-builder.sjs?html=tab"
|
|
);
|
|
const browsingContext = tab.linkedBrowser.browsingContext;
|
|
const contextDescriptor = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext.browserId,
|
|
};
|
|
const contextDescriptorAll = {
|
|
type: ContextDescriptorType.All,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
info("Add an listener for eventemitter.testEvent");
|
|
const events = [];
|
|
const onEvent = (event, data) => events.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 1);
|
|
|
|
info(
|
|
"Add another listener for eventemitter.testEvent, using global context"
|
|
);
|
|
const eventsAll = [];
|
|
const onEventAll = (event, data) => eventsAll.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptorAll,
|
|
onEventAll
|
|
);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 1);
|
|
is(events.length, 2);
|
|
|
|
info("Remove the first listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
|
|
info("Check that we are still subscribed to eventemitter.testEvent");
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 2);
|
|
is(events.length, 2);
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptorAll,
|
|
onEventAll
|
|
);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 2);
|
|
is(events.length, 2);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Check that adding and removing first listener for the global context and then
|
|
* for the specific context works as expected.
|
|
*/
|
|
add_task(
|
|
async function test_global_event_listener_and_then_remove_context_event_listener() {
|
|
const tab = await addTab(
|
|
"https://example.com/document-builder.sjs?html=tab"
|
|
);
|
|
const browsingContext = tab.linkedBrowser.browsingContext;
|
|
const contextDescriptor = {
|
|
type: ContextDescriptorType.TopBrowsingContext,
|
|
id: browsingContext.browserId,
|
|
};
|
|
const contextDescriptorAll = {
|
|
type: ContextDescriptorType.All,
|
|
};
|
|
|
|
const root = createRootMessageHandler("session-id-event");
|
|
const monitoringEvents = await setupEventMonitoring(root);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
|
|
info("Add an listener for eventemitter.testEvent");
|
|
const events = [];
|
|
const onEvent = (event, data) => events.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(events.length, 1);
|
|
|
|
info(
|
|
"Add another listener for eventemitter.testEvent, using global context"
|
|
);
|
|
const eventsAll = [];
|
|
const onEventAll = (event, data) => eventsAll.push(data.text);
|
|
await root.eventsDispatcher.on(
|
|
"eventemitter.testEvent",
|
|
contextDescriptorAll,
|
|
onEventAll
|
|
);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 1);
|
|
is(events.length, 2);
|
|
|
|
info("Remove the global listener for eventemitter.testEvent");
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptorAll,
|
|
onEventAll
|
|
);
|
|
|
|
info(
|
|
"Check that we are still subscribed to eventemitter.testEvent for the specific context"
|
|
);
|
|
is(await isSubscribed(root, browsingContext), true);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 1);
|
|
is(events.length, 3);
|
|
|
|
await root.eventsDispatcher.off(
|
|
"eventemitter.testEvent",
|
|
contextDescriptor,
|
|
onEvent
|
|
);
|
|
|
|
is(await isSubscribed(root, browsingContext), false);
|
|
await emitTestEvent(root, browsingContext, monitoringEvents);
|
|
is(eventsAll.length, 1);
|
|
is(events.length, 3);
|
|
|
|
root.destroy();
|
|
gBrowser.removeTab(tab);
|
|
}
|
|
);
|
|
|
|
async function setupEventMonitoring(root) {
|
|
const monitoringEvents = [];
|
|
const onMonitoringEvent = (event, data) => monitoringEvents.push(data.text);
|
|
root.on("eventemitter.monitoringEvent", onMonitoringEvent);
|
|
|
|
registerCleanupFunction(() =>
|
|
root.off("eventemitter.monitoringEvent", onMonitoringEvent)
|
|
);
|
|
|
|
return monitoringEvents;
|
|
}
|
|
|
|
async function emitTestEvent(root, browsingContext, monitoringEvents) {
|
|
const count = monitoringEvents.length;
|
|
info("Call eventemitter.emitTestEvent");
|
|
await root.handleCommand({
|
|
moduleName: "eventemitter",
|
|
commandName: "emitTestEvent",
|
|
destination: {
|
|
type: WindowGlobalMessageHandler.type,
|
|
id: browsingContext.id,
|
|
},
|
|
});
|
|
|
|
// The monitoring event is always emitted, regardless of the status of the
|
|
// module. Wait for catching this event before resuming the assertions.
|
|
info("Wait for the monitoring event");
|
|
await BrowserTestUtils.waitForCondition(
|
|
() => monitoringEvents.length >= count + 1
|
|
);
|
|
is(monitoringEvents.length, count + 1);
|
|
}
|
|
|
|
function isSubscribed(root, browsingContext) {
|
|
info("Call eventemitter.isSubscribed");
|
|
return root.handleCommand({
|
|
moduleName: "eventemitter",
|
|
commandName: "isSubscribed",
|
|
destination: {
|
|
type: WindowGlobalMessageHandler.type,
|
|
id: browsingContext.id,
|
|
},
|
|
});
|
|
}
|