tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit df5ae350decc3b64eacb6a44cd7f095d9b003434
parent b224e97d13d9a4965f963f53e5823a4c019aa445
Author: Julian Descottes <jdescottes@mozilla.com>
Date:   Tue, 28 Oct 2025 09:11:28 +0000

Bug 1979731 - [remote] Expose events from UserContextManager r=Sasha

The side effect of this change is that UUID of the user context is no longer found in the name of that user context. I initially did this to make it easier to debug, but in the end I don't think we rely much on the user context name, so as long as it is unique it should be fine.

Differential Revision: https://phabricator.services.mozilla.com/D270214

Diffstat:
Mremote/shared/UserContextManager.sys.mjs | 29++++++++++++++++++-----------
Mremote/shared/test/browser/browser_UserContextManager.js | 24++++++++++++++++++++++++
2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/remote/shared/UserContextManager.sys.mjs b/remote/shared/UserContextManager.sys.mjs @@ -7,6 +7,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.sys.mjs", + EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs", ContextualIdentityListener: "chrome://remote/content/shared/listeners/ContextualIdentityListener.sys.mjs", @@ -23,12 +24,21 @@ const DEFAULT_INTERNAL_ID = 0; * * This class is exported for test purposes. Otherwise the UserContextManager * singleton should be used. + * + * @fires user-context-created + * - {string} userContextId + * The UUID of the user context which was just created. + * @fires user-context-deleted + * - {string} userContextId + * The UUID of the user context which was just deleted. */ export class UserContextManagerClass { #contextualIdentityListener; #userContextIds; constructor() { + lazy.EventEmitter.decorate(this); + // Map from internal ids (numbers) from the ContextualIdentityService to // opaque UUIDs (string). this.#userContextIds = new Map(); @@ -76,19 +86,14 @@ export class UserContextManagerClass { * The user context id of the new user context. */ createContext(prefix = "remote") { - // Prepare the opaque id and name beforehand. - const userContextId = lazy.generateUUID(); - const name = `${prefix}-${userContextId}`; + // Prepare a unique name. + const name = `${prefix}-${lazy.generateUUID()}`; // Create the user context. const identity = lazy.ContextualIdentityService.create(name); - const internalId = identity.userContextId; // An id has been set already by the contextual-identity-created observer. - // Override it with `userContextId` to match the container name. - this.#userContextIds.set(internalId, userContextId); - - return userContextId; + return this.#userContextIds.get(identity.userContextId); } /** @@ -226,13 +231,15 @@ export class UserContextManagerClass { }; #onIdentityDeleted = (eventName, data) => { + const userContextId = this.#userContextIds.get(data.identity.userContextId); this.#userContextIds.delete(data.identity.userContextId); + this.emit("user-context-deleted", { userContextId }); }; #registerIdentity(identity) { - // Note: the id for identities created via UserContextManagerClass.createContext - // are overridden in createContext. - this.#userContextIds.set(identity.userContextId, lazy.generateUUID()); + const userContextId = lazy.generateUUID(); + this.#userContextIds.set(identity.userContextId, userContextId); + this.emit("user-context-created", { userContextId }); } } diff --git a/remote/shared/test/browser/browser_UserContextManager.js b/remote/shared/test/browser/browser_UserContextManager.js @@ -142,6 +142,30 @@ add_task(async function test_create_context_prefix() { userContextManager.destroy(); }); +add_task(async function test_events() { + const manager = new UserContextManagerClass(); + const userContextCreatedEvents = []; + const userContextDeletedEvents = []; + manager.on("user-context-created", (name, data) => + userContextCreatedEvents.push(data) + ); + manager.on("user-context-deleted", (name, data) => + userContextDeletedEvents.push(data) + ); + + const contextId1 = manager.createContext(); + is(userContextCreatedEvents.length, 1); + is(userContextCreatedEvents[0].userContextId, contextId1); + is(userContextDeletedEvents.length, 0); + + manager.removeUserContext(contextId1); + is(userContextCreatedEvents.length, 1); + is(userContextDeletedEvents.length, 1); + is(userContextDeletedEvents[0].userContextId, contextId1); + + manager.destroy(); +}); + add_task(async function test_several_managers() { const manager1 = new UserContextManagerClass(); const manager2 = new UserContextManagerClass();