diff options
Diffstat (limited to 'browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs')
-rw-r--r-- | browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs | 94 |
1 files changed, 75 insertions, 19 deletions
diff --git a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs index a6941cbd0a..8e76ad53db 100644 --- a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs +++ b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs @@ -27,6 +27,12 @@ ChromeUtils.defineLazyGetter(lazy, "logger", () => const PRIVATE_USER_CONTEXT_ID = -1; /** + * Maps the open tabs by userContextId. + * Each entry is a Map of url => count. + */ +var gOpenTabUrls = new Map(); + +/** * Class used to create the provider. */ export class UrlbarProviderOpenTabs extends UrlbarProvider { @@ -57,10 +63,9 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { * If this method returns false, the providers manager won't start a query * with this provider, to save on resources. * - * @param {UrlbarQueryContext} queryContext The query context object * @returns {boolean} Whether this provider should be invoked for the search. */ - isActive(queryContext) { + isActive() { // For now we don't actually use this provider to query open tabs, instead // we join the temp table in UrlbarProviderPlaces. return false; @@ -74,26 +79,59 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { static memoryTableInitialized = false; /** - * Maps the open tabs by userContextId. - * Each entry is a Map of url => count. - */ - static _openTabs = new Map(); - - /** * Return unique urls that are open for given user context id. * - * @param {integer} userContextId Containers user context id + * @param {integer|string} userContextId Containers user context id * @param {boolean} [isInPrivateWindow] In private browsing window or not * @returns {Array} urls */ - static getOpenTabs(userContextId, isInPrivateWindow = false) { + static getOpenTabUrlsForUserContextId( + userContextId, + isInPrivateWindow = false + ) { + // It's fairly common to retrieve the value from an HTML attribute, that + // means we're getting sometimes a string, sometimes an integer. As we're + // using this as key of a Map, we must treat it consistently. + userContextId = parseInt(userContextId); userContextId = UrlbarProviderOpenTabs.getUserContextIdForOpenPagesTable( userContextId, isInPrivateWindow ); - return Array.from( - UrlbarProviderOpenTabs._openTabs.get(userContextId)?.keys() ?? [] - ); + return Array.from(gOpenTabUrls.get(userContextId)?.keys() ?? []); + } + + /** + * Return unique urls that are open, along with their user context id. + * + * @param {boolean} [isInPrivateWindow] Whether it's for a private browsing window + * @returns {Map} { url => Set({userContextIds}) } + */ + static getOpenTabUrls(isInPrivateWindow = false) { + let uniqueUrls = new Map(); + if (isInPrivateWindow) { + let urls = UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId( + PRIVATE_USER_CONTEXT_ID, + true + ); + for (let url of urls) { + uniqueUrls.set(url, new Set([PRIVATE_USER_CONTEXT_ID])); + } + } else { + for (let [userContextId, urls] of gOpenTabUrls) { + if (userContextId == PRIVATE_USER_CONTEXT_ID) { + continue; + } + for (let url of urls.keys()) { + let userContextIds = uniqueUrls.get(url); + if (!userContextIds) { + userContextIds = new Set(); + uniqueUrls.set(url, userContextIds); + } + userContextIds.add(userContextId); + } + } + } + return uniqueUrls; } /** @@ -155,7 +193,7 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { // Must be set before populating. UrlbarProviderOpenTabs.memoryTableInitialized = true; // Populate the table with the current cached tabs. - for (let [userContextId, entries] of UrlbarProviderOpenTabs._openTabs) { + for (let [userContextId, entries] of gOpenTabUrls) { for (let [url, count] of entries) { await addToMemoryTable(url, userContextId, count).catch( console.error @@ -168,10 +206,22 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { * Registers a tab as open. * * @param {string} url Address of the tab - * @param {integer} userContextId Containers user context id + * @param {integer|string} userContextId Containers user context id * @param {boolean} isInPrivateWindow In private browsing window or not */ static async registerOpenTab(url, userContextId, isInPrivateWindow) { + // It's fairly common to retrieve the value from an HTML attribute, that + // means we're getting sometimes a string, sometimes an integer. As we're + // using this as key of a Map, we must treat it consistently. + userContextId = parseInt(userContextId); + if (!Number.isInteger(userContextId)) { + lazy.logger.error("Invalid userContextId while registering openTab: ", { + url, + userContextId, + isInPrivateWindow, + }); + return; + } lazy.logger.info("Registering openTab: ", { url, userContextId, @@ -182,10 +232,10 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { isInPrivateWindow ); - let entries = UrlbarProviderOpenTabs._openTabs.get(userContextId); + let entries = gOpenTabUrls.get(userContextId); if (!entries) { entries = new Map(); - UrlbarProviderOpenTabs._openTabs.set(userContextId, entries); + gOpenTabUrls.set(userContextId, entries); } entries.set(url, (entries.get(url) ?? 0) + 1); await addToMemoryTable(url, userContextId).catch(console.error); @@ -195,10 +245,14 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { * Unregisters a previously registered open tab. * * @param {string} url Address of the tab - * @param {integer} userContextId Containers user context id + * @param {integer|string} userContextId Containers user context id * @param {boolean} isInPrivateWindow In private browsing window or not */ static async unregisterOpenTab(url, userContextId, isInPrivateWindow) { + // It's fairly common to retrieve the value from an HTML attribute, that + // means we're getting sometimes a string, sometimes an integer. As we're + // using this as key of a Map, we must treat it consistently. + userContextId = parseInt(userContextId); lazy.logger.info("Unregistering openTab: ", { url, userContextId, @@ -209,7 +263,7 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { isInPrivateWindow ); - let entries = UrlbarProviderOpenTabs._openTabs.get(userContextId); + let entries = gOpenTabUrls.get(userContextId); if (entries) { let oldCount = entries.get(url); if (oldCount == 0) { @@ -218,6 +272,8 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { } if (oldCount == 1) { entries.delete(url); + // Note: `entries` might be an empty Map now, though we don't remove it + // from `gOpenTabUrls` as it's likely to be reused later. } else { entries.set(url, oldCount - 1); } |