tor-browser

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

commit 5a5b3741981250310f4327537f18879559779f9c
parent 9229a40eb065a0bef662e59275e14c90c58f3d9b
Author: Nathan Barrett <nbarrett@mozilla.com>
Date:   Wed,  3 Dec 2025 00:06:28 +0000

Bug 2002079 - Poll places DB for high frecency sponsored topsites r=home-newtab-reviewers,thecount

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

Diffstat:
Mbrowser/extensions/newtab/lib/TopSitesFeed.sys.mjs | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 90 insertions(+), 4 deletions(-)

diff --git a/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs b/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs @@ -1320,13 +1320,98 @@ export class TopSitesFeed { } /** + * Dedupe sponsored domains against organic topsites. + * + * @param {Array} sponsors - List of sponsor domain objects + * @returns {Array} Filtered list of sponsors not in organic topsites + */ + dedupeSponsorsAgainstTopsites(sponsors) { + const topsites = new Set( + (this._linksWithDefaults || []) + .filter(site => site.type !== "frecency-boost") + .map(site => { + try { + return new URL(site.url).hostname; + } catch (e) { + return null; + } + }) + .filter(Boolean) + ); + + return sponsors.filter(({ domain }) => !topsites.has(domain)); + } + + /** + * Build frecency-boosted spocs from a list of sponsor domains by checking Places history. + * Checks if domains exist in history with favicons, dedupes against organic + * topsites, and returns all matches sorted by frecency. + * + * @param {Array} sponsors - List of sponsor domain objects with domain and title + * @returns {Array} Array of sponsored tile objects sorted by frecency, or empty array + */ + async buildFrecencyBoostedSpocs(sponsors) { + if (!sponsors || !sponsors.length) { + return []; + } + + const sponsorsToCheck = this.dedupeSponsorsAgainstTopsites(sponsors); + + if (!sponsorsToCheck.length) { + return []; + } + + let pagesMap; + try { + pagesMap = await lazy.PlacesUtils.history.fetchMany( + sponsorsToCheck.map(({ domain }) => `https://${domain}`) + ); + } catch (error) { + lazy.log.warn(`Failed to fetch history data: ${error.message}`); + return []; + } + + const candidates = []; + for (const domainObj of sponsorsToCheck) { + const url = `https://${domainObj.domain}/`; + const page = pagesMap.get(url); + + if (!page) { + continue; + } + + candidates.push({ + hostname: domainObj.domain, + url, + label: domainObj.title, + sponsored_position: 3, + partner: SPONSORED_TILE_PARTNER_FREC_BOOST, + type: "frecency-boost", + frecency: page.frecency, + show_sponsored_label: true, + }); + } + + candidates.sort((a, b) => b.frecency - a.frecency); + return candidates; + } + + /** * Fetch topsites spocs that are frecency boosted. * * @returns {Array} An array of sponsored tile objects. */ - fetchFrecencyBoostedSpocs() { - let sponsored = []; - return sponsored; + async fetchFrecencyBoostedSpocs() { + if (!this._contile.sovEnabled() || this._linksWithDefaults.length === 0) { + return []; + } + const domainData = {}; + // Get domains for current region + const userRegion = lazy.Region.home || ""; + const domainList = domainData[userRegion] || []; + + // Find all matches from the test domains, sorted by frecency + return this.buildFrecencyBoostedSpocs(domainList); } /** @@ -1502,7 +1587,7 @@ export class TopSitesFeed { ); const discoverySponsored = this.fetchDiscoveryStreamSpocs(); - const frecencyBoostedSponsored = this.fetchFrecencyBoostedSpocs(); + const frecencyBoostedSponsored = await this.fetchFrecencyBoostedSpocs(); this._telemetryUtility.setTiles(discoverySponsored); const sponsored = this._mergeSponsoredLinks({ @@ -1802,6 +1887,7 @@ export class TopSitesFeed { if (!this._contile.sov) { return; } + // This sample input should ensure we return the same result for this allocation, // even if called from other parts of the code. let contextId = await lazy.ContextId.request();