Bug 1694145 - [remote] Add removeSessionData API to RootMessageHandler r=webdriver-reviewers,whimboo

Depends on D132150

Adds a new API to RootMessageHandler which will be necessary to implement _unsubscribeEvent on root/log.jsm
Expand the current browser mochitest for session data to cover the new API.

Differential Revision: https://phabricator.services.mozilla.com/D132152
This commit is contained in:
Julian Descottes 2021-12-02 19:21:44 +00:00
parent a9e76a12f8
commit 3893d96e96
6 changed files with 138 additions and 49 deletions

View File

@ -86,33 +86,7 @@ class RootMessageHandler extends MessageHandler {
* MessageHandlers.
*/
addSessionData(sessionData = {}) {
const { moduleName, category, contextDescriptor, values } = sessionData;
const addedValues = this._sessionData.addSessionData(
moduleName,
category,
contextDescriptor,
values
);
if (addedValues.length == 0) {
// Avoid unnecessary broadcast if no value was added.
return [];
}
return this.handleCommand({
moduleName,
commandName: "_applySessionData",
params: {
values: addedValues,
category,
},
destination: {
type: WindowGlobalMessageHandler.type,
contextDescriptor: {
type: CONTEXT_DESCRIPTOR_TYPES.ALL,
},
},
});
return this._updateSessionData(sessionData, { mode: "add" });
}
/**
@ -134,4 +108,57 @@ class RootMessageHandler extends MessageHandler {
);
}
}
/**
* Remove session data items of a given module, category and
* contextDescriptor.
*
* Forwards the call to the SessionData instance owned by this
* RootMessageHandler and propagates the information via a command to existing
* MessageHandlers.
*/
removeSessionData(sessionData = {}) {
return this._updateSessionData(sessionData, { mode: "remove" });
}
_updateSessionData(sessionData, options = {}) {
const { mode } = options;
// TODO: We currently only support adding or removing items separately.
// Supporting both will be added with transactions in Bug 1741834.
if (mode != "add" && mode != "remove") {
throw new Error(`Unsupported mode for _updateSessionData ${mode}`);
}
const { moduleName, category, contextDescriptor, values } = sessionData;
const isAdding = mode === "add";
const updateMethod = isAdding ? "addSessionData" : "removeSessionData";
const updatedValues = this._sessionData[updateMethod](
moduleName,
category,
contextDescriptor,
values
);
if (updatedValues.length == 0) {
// Avoid unnecessary broadcast if no value was removed.
return [];
}
return this.handleCommand({
moduleName,
commandName: "_applySessionData",
params: {
[isAdding ? "added" : "removed"]: updatedValues,
category,
},
destination: {
type: WindowGlobalMessageHandler.type,
contextDescriptor: {
type: CONTEXT_DESCRIPTOR_TYPES.ALL,
},
},
});
}
}

View File

@ -89,7 +89,7 @@ class WindowGlobalMessageHandler extends MessageHandler {
// moduleName & category, but with different values. Instead we can
// use the fact that _applySessionData supports arrays of values,
// though it will make the implementation more complex.
values: [value],
added: [value],
},
destination: {
type: WindowGlobalMessageHandler.type,

View File

@ -228,6 +228,11 @@ class SessionData {
return removedValues;
}
updateSessionData(moduleName, category, contextDescriptor, added, removed) {
this.addSessionData(moduleName, category, contextDescriptor, added);
this.removeSessionData(moduleName, category, contextDescriptor, removed);
}
_isSameItem(item1, item2) {
const descriptor1 = item1.contextDescriptor;
const descriptor2 = item2.contextDescriptor;

View File

@ -17,45 +17,73 @@ add_task(async function test_session_data_broadcast() {
const root = createRootMessageHandler("session-id-event");
info("Add a new session data item, expect one return value");
const value1 = await sendAddSessionData(root, ["text-1"]);
const value1 = await addSessionData(root, ["text-1"]);
is(value1.length, 1);
is(value1[0].newData, "text-1");
is(value1[0].addedData, "text-1");
is(value1[0].removedData, "");
is(value1[0].sessionData, "text-1");
is(value1[0].contextId, browsingContext1.id);
info("Add two session data items, expect one return value with both items");
const value2 = await sendAddSessionData(root, ["text-2", "text-3"]);
const value2 = await addSessionData(root, ["text-2", "text-3"]);
is(value2.length, 1);
is(value2[0].newData, "text-2, text-3");
is(value2[0].addedData, "text-2, text-3");
is(value2[0].removedData, "");
is(value2[0].sessionData, "text-1, text-2, text-3");
is(value2[0].contextId, browsingContext1.id);
info("Try to add an existing data item, expect no return value");
const value3 = await sendAddSessionData(root, ["text-1"]);
const value3 = await addSessionData(root, ["text-1"]);
is(value3.length, 0);
info("Add an existing and a new item, expect only the new item to return");
const value4 = await sendAddSessionData(root, ["text-1", "text-4"]);
const value4 = await addSessionData(root, ["text-1", "text-4"]);
is(value4.length, 1);
is(value4[0].newData, "text-4");
is(value4[0].addedData, "text-4");
is(value4[0].removedData, "");
is(value4[0].sessionData, "text-1, text-2, text-3, text-4");
is(value4[0].contextId, browsingContext1.id);
info("Remove an item, expect only the new item to return");
const value5 = await removeSessionData(root, ["text-3"]);
is(value5.length, 1);
is(value5[0].addedData, "");
is(value5[0].removedData, "text-3");
is(value5[0].sessionData, "text-1, text-2, text-4");
is(value5[0].contextId, browsingContext1.id);
info("Open a new tab on the same test URL");
const tab2 = await addTab(TEST_PAGE);
const browsingContext2 = tab2.linkedBrowser.browsingContext;
info("Add a new session data item, check both contexts have the same data.");
const value5 = await sendAddSessionData(root, ["text-5"]);
is(value5.length, 2);
is(value5[0].newData, "text-5");
is(value5[0].sessionData, "text-1, text-2, text-3, text-4, text-5");
is(value5[0].contextId, browsingContext1.id);
is(value5[1].newData, "text-5");
// "text-1, text-2, text-3, text-4" were added as initial session data and
const value6 = await addSessionData(root, ["text-5"]);
is(value6.length, 2);
is(value6[0].addedData, "text-5");
is(value6[0].removedData, "");
is(value6[0].sessionData, "text-1, text-2, text-4, text-5");
is(value6[0].contextId, browsingContext1.id);
is(value6[1].addedData, "text-5");
// "text-1, text-2, text-4" were added as initial session data and
// "text-5" was added afterwards.
is(value5[1].sessionData, "text-1, text-2, text-3, text-4, text-5");
is(value5[1].contextId, browsingContext2.id);
is(value6[1].sessionData, "text-1, text-2, text-4, text-5");
is(value6[1].contextId, browsingContext2.id);
info("Remove a missing item, expect no return value");
const value7 = await removeSessionData(root, ["text-missing"]);
is(value7.length, 0);
info("Remove an existing and a missing item");
const value8 = await removeSessionData(root, ["text-2", "text-missing"]);
is(value8.length, 2);
is(value8[0].addedData, "");
is(value8[0].removedData, "text-2");
is(value8[0].sessionData, "text-1, text-4, text-5");
is(value8[0].contextId, browsingContext1.id);
is(value8[1].addedData, "");
is(value8[1].removedData, "text-2");
is(value8[1].sessionData, "text-1, text-4, text-5");
is(value8[1].contextId, browsingContext2.id);
root.destroy();
@ -63,7 +91,7 @@ add_task(async function test_session_data_broadcast() {
gBrowser.removeTab(tab2);
});
function sendAddSessionData(rootMessageHandler, values) {
function addSessionData(rootMessageHandler, values) {
return rootMessageHandler.handleCommand({
moduleName: "command",
commandName: "testAddSessionData",
@ -75,3 +103,16 @@ function sendAddSessionData(rootMessageHandler, values) {
},
});
}
function removeSessionData(rootMessageHandler, values) {
return rootMessageHandler.handleCommand({
moduleName: "command",
commandName: "testRemoveSessionData",
destination: {
type: RootMessageHandler.type,
},
params: {
values,
},
});
}

View File

@ -32,6 +32,17 @@ class Command extends Module {
});
}
testRemoveSessionData(params) {
return this.messageHandler.removeSessionData({
moduleName: "command",
category: "testCategory",
contextDescriptor: {
type: CONTEXT_DESCRIPTOR_TYPES.ALL,
},
values: params.values,
});
}
testRootModule() {
return "root-value";
}

View File

@ -25,11 +25,16 @@ class Command extends Module {
_applySessionData(params) {
if (params.category === "testCategory") {
this._testCategorySessionData = this._testCategorySessionData.concat(
params.values
);
const added = params.added || [];
const removed = params.removed || [];
this._testCategorySessionData = this._testCategorySessionData
.concat(added)
.filter(value => !removed.includes(value));
return {
newData: params.values.join(", "),
addedData: added.join(", "),
removedData: removed.join(", "),
sessionData: this._testCategorySessionData.join(", "),
contextId: this.messageHandler.contextId,
};