tor-browser

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

commit bc4dae42f9df10e46aa3dd74e6dc1a16ec2bb0b7
parent c14367dcaf72b3d880a474e8bc05382954e045d2
Author: Tom Zhang <tzhang@mozilla.com>
Date:   Wed, 31 Dec 2025 00:28:59 +0000

Bug 2007444 - Fix pulling description for current tab; added browser test r=omarg,ai-models-reviewers,bjohns

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

Diffstat:
Mbrowser/components/aiwindow/models/ChatUtils.sys.mjs | 22++++++++++++++++++----
Mbrowser/components/aiwindow/models/tests/browser/browser.toml | 1+
Abrowser/components/aiwindow/models/tests/browser/browser_getCurrentTabMetadata.js | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/aiwindow/models/tests/xpcshell/test_ChatUtils.js | 41+++++++++++++++++++++++++++++++----------
4 files changed, 219 insertions(+), 14 deletions(-)

diff --git a/browser/components/aiwindow/models/ChatUtils.sys.mjs b/browser/components/aiwindow/models/ChatUtils.sys.mjs @@ -62,10 +62,24 @@ export async function getCurrentTabMetadata(depsOverride) { let description = ""; if (url) { - description = - PageDataService.getCached(url)?.description || - (await PageDataService.fetchPageData(url))?.description || - ""; + const cachedData = PageDataService.getCached(url); + if (cachedData?.description) { + description = cachedData.description; + } else { + try { + const actor = + browser.browsingContext?.currentWindowGlobal?.getActor("PageData"); + if (actor) { + const pageData = await actor.collectPageData(); + description = pageData?.description || ""; + } + } catch (e) { + console.error( + "Failed to collect page description data from current tab:", + e + ); + } + } } return { url, title, description }; diff --git a/browser/components/aiwindow/models/tests/browser/browser.toml b/browser/components/aiwindow/models/tests/browser/browser.toml @@ -6,5 +6,6 @@ prefs = [ "browser.aiwindow.enabled=true", ] +["browser_getCurrentTabMetadata.js"] ["browser_get_page_content.js"] window_attributes = "ai-window" diff --git a/browser/components/aiwindow/models/tests/browser/browser_getCurrentTabMetadata.js b/browser/components/aiwindow/models/tests/browser/browser_getCurrentTabMetadata.js @@ -0,0 +1,169 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { getCurrentTabMetadata } = ChromeUtils.importESModule( + "moz-src:///browser/components/aiwindow/models/ChatUtils.sys.mjs" +); + +const { PageDataService } = ChromeUtils.importESModule( + "moz-src:///browser/components/pagedata/PageDataService.sys.mjs" +); + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["browser.pagedata.enabled", true]], + }); + + PageDataService.init(); + + registerCleanupFunction(() => { + PageDataService.uninit(); + }); +}); + +add_task(async function test_getCurrentTabMetadata_basic() { + const html = ` + <!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <title>Test Page Title</title> + <meta name="description" content="This is a test page description"> + </head> + <body> + <h1>Test Page Content</h1> + </body> + </html> + `; + + const { url, server } = serveHTML(html); + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url, true); + + try { + const metadata = await getCurrentTabMetadata(); + + is(metadata.url, url, "Should return the correct URL"); + is(metadata.title, "Test Page Title", "Should return the correct title"); + Assert.strictEqual( + typeof metadata.description, + "string", + "Should return a string description" + ); + } finally { + BrowserTestUtils.removeTab(tab); + await new Promise(resolve => server.stop(resolve)); + } +}); + +add_task(async function test_getCurrentTabMetadata_no_description() { + const html = ` + <!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <title>Page Without Description</title> + </head> + <body> + <p>This page has no description metadata.</p> + </body> + </html> + `; + + const { url, server } = serveHTML(html); + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url, true); + + try { + const metadata = await getCurrentTabMetadata(); + + is(metadata.url, url, "Should return the correct URL"); + is( + metadata.title, + "Page Without Description", + "Should return the correct title" + ); + is( + metadata.description, + "", + "Should return empty string when no description available" + ); + } finally { + BrowserTestUtils.removeTab(tab); + await new Promise(resolve => server.stop(resolve)); + } +}); + +add_task(async function test_getCurrentTabMetadata_about_blank() { + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:blank", + true + ); + + try { + const metadata = await getCurrentTabMetadata(); + + is(metadata.url, "about:blank", "Should handle about:blank URL"); + Assert.notStrictEqual( + metadata.title, + undefined, + "Should have a title (may be empty)" + ); + is( + metadata.description, + "", + "Should have empty description for about:blank" + ); + } finally { + BrowserTestUtils.removeTab(tab); + } +}); + +add_task(async function test_getCurrentTabMetadata_with_cached_data() { + const html = ` + <!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <title>Cached Test Page</title> + <meta name="description" content="Cached page description"> + </head> + <body> + <p>Testing cached metadata.</p> + </body> + </html> + `; + + const { url, server } = serveHTML(html); + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url, true); + + try { + // Lock the entry first to create a cache entry + const browser = tab.linkedBrowser; + PageDataService.lockEntry(browser, url); + + // Now add the cached data + PageDataService.pageDataDiscovered({ + url, + date: Date.now(), + description: "Test cached description", + }); + + const metadata = await getCurrentTabMetadata(); + + is(metadata.url, url, "Should return the correct URL"); + is(metadata.title, "Cached Test Page", "Should return the correct title"); + is( + metadata.description, + "Cached page description", + "Should return cached description" + ); + + // Unlock the entry in cleanup + PageDataService.unlockEntry(browser, url); + } finally { + BrowserTestUtils.removeTab(tab); + await new Promise(resolve => server.stop(resolve)); + } +}); diff --git a/browser/components/aiwindow/models/tests/xpcshell/test_ChatUtils.js b/browser/components/aiwindow/models/tests/xpcshell/test_ChatUtils.js @@ -108,21 +108,27 @@ add_task(async function test_getCurrentTabMetadata_fetch_fallback() { const tracker = { getTopWindow: sb.stub() }; const pageData = { getCached: sb.stub(), - fetchPageData: sb.stub(), + }; + const fakeActor = { + collectPageData: sb.stub().resolves({ + description: "Collected description", + }), }; const fakeBrowser = { currentURI: { spec: "https://example.com/article" }, contentTitle: "", documentTitle: "Example Article", + browsingContext: { + currentWindowGlobal: { + getActor: sb.stub().returns(fakeActor), + }, + }, }; tracker.getTopWindow.returns({ gBrowser: { selectedBrowser: fakeBrowser }, }); pageData.getCached.returns(null); - const fetchStub = pageData.fetchPageData.resolves({ - description: "Fetched description", - }); try { const result = await getCurrentTabMetadata({ @@ -132,9 +138,18 @@ add_task(async function test_getCurrentTabMetadata_fetch_fallback() { Assert.deepEqual(result, { url: "https://example.com/article", title: "Example Article", - description: "Fetched description", + description: "Collected description", }); - Assert.ok(fetchStub.calledOnce, "Should fetch description when not cached"); + Assert.ok( + fakeActor.collectPageData.calledOnce, + "Should collect page data from actor when not cached" + ); + Assert.ok( + fakeBrowser.browsingContext.currentWindowGlobal.getActor.calledWith( + "PageData" + ), + "Should get PageData actor" + ); } finally { sb.restore(); } @@ -146,13 +161,20 @@ add_task( const tracker = { getTopWindow: sb.stub() }; const pageData = { getCached: sb.stub(), - fetchPageData: sb.stub(), }; const locale = Services.locale.appLocaleAsBCP47; + const fakeActor = { + collectPageData: sb.stub(), + }; const fakeBrowser = { currentURI: { spec: "https://mozilla.org" }, contentTitle: "Mozilla", documentTitle: "Mozilla", + browsingContext: { + currentWindowGlobal: { + getActor: sb.stub().returns(fakeActor), + }, + }, }; tracker.getTopWindow.returns({ @@ -161,7 +183,6 @@ add_task( pageData.getCached.returns({ description: "Internet for people", }); - const fetchStub = pageData.fetchPageData; const clock = sb.useFakeTimers({ now: Date.UTC(2025, 11, 27, 14, 0, 0) }); try { @@ -191,8 +212,8 @@ add_task( "Should include tab description" ); Assert.ok( - fetchStub.notCalled, - "Should not fetch when cached data exists" + fakeActor.collectPageData.notCalled, + "Should not collect page data when cached data exists" ); } finally { clock.restore();