tor-browser

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

commit dc4e9d14937fb0fff9c2cc427826df18002bd4fb
parent 8e2ce9cb378d9cf2dd174e85dd69b8b149fbf0e6
Author: Molly Shillabeer <mshillabeer@mozilla.com>
Date:   Tue, 30 Dec 2025 21:20:20 +0000

Bug 2007938 - Add check for history enablement for New Tab conversation starters r=tzhang,ai-models-reviewers

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

Diffstat:
Mbrowser/components/aiwindow/models/ConversationSuggestions.sys.mjs | 30++++++++++++++++++++++--------
Mbrowser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js | 241+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
2 files changed, 196 insertions(+), 75 deletions(-)

diff --git a/browser/components/aiwindow/models/ConversationSuggestions.sys.mjs b/browser/components/aiwindow/models/ConversationSuggestions.sys.mjs @@ -114,9 +114,9 @@ export const NewTabStarterGenerator = { // TODO: discuss with design about updating phrasing to "pages" instead of "tabs" browsingPrompts: [ - { text: "Find tabs in history", minTabs: 0 }, - { text: "Summarize tabs", minTabs: 1 }, - { text: "Compare tabs", minTabs: 2 }, + { text: "Find tabs in history", minTabs: 0, needsHistory: true }, + { text: "Summarize tabs", minTabs: 1, needsHistory: false }, + { text: "Compare tabs", minTabs: 2, needsHistory: false }, ], getRandom(arr) { @@ -124,27 +124,41 @@ export const NewTabStarterGenerator = { }, /** - * Generate conversation starter prompts based on number of open tabs + * Generate conversation starter prompts based on number of open tabs and browsing history prefs. + * "places.history.enabled" covers "Remember browsing and download history" while + * "browser.privatebrowsing.autostart" covers "Always use private mode" and "Never remember history". + * We need to check both prefs to cover all cases where history can be disabled. * * @param {number} tabCount - number of open tabs * @returns {Promise<Array>} Array of {text, type} suggestion objects */ async getPrompts(tabCount) { + const historyEnabled = Services.prefs.getBoolPref("places.history.enabled"); + const privateBrowsing = Services.prefs.getBoolPref( + "browser.privatebrowsing.autostart" + ); const validBrowsingPrompts = this.browsingPrompts.filter( - p => tabCount >= p.minTabs + p => + tabCount >= p.minTabs && + (!p.needsHistory || (historyEnabled && !privateBrowsing)) ); const writingPrompt = this.getRandom(this.writingPrompts); const planningPrompt = this.getRandom(this.planningPrompts); const browsingPrompt = validBrowsingPrompts.length ? this.getRandom(validBrowsingPrompts) - : this.browsingPrompts[0]; + : null; - return [ + const prompts = [ { text: writingPrompt, type: "chat" }, { text: planningPrompt, type: "chat" }, - { text: browsingPrompt.text, type: "chat" }, ]; + + if (browsingPrompt) { + prompts.push({ text: browsingPrompt.text, type: "chat" }); + } + + return prompts; }, }; diff --git a/browser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js b/browser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js @@ -35,6 +35,8 @@ const { sinon } = ChromeUtils.importESModule( const PREF_API_KEY = "browser.aiwindow.apiKey"; const PREF_ENDPOINT = "browser.aiwindow.endpoint"; const PREF_MODEL = "browser.aiwindow.model"; +const PREF_HISTORY_ENABLED = "places.history.enabled"; +const PREF_PRIVATE_BROWSING = "browser.privatebrowsing.autostart"; const API_KEY = "test-api-key"; const ENDPOINT = "https://api.test-endpoint.com/v1"; @@ -44,7 +46,13 @@ const MODEL = "test-model"; * Cleans up preferences after testing */ registerCleanupFunction(() => { - for (let pref of [PREF_API_KEY, PREF_ENDPOINT, PREF_MODEL]) { + for (let pref of [ + PREF_API_KEY, + PREF_ENDPOINT, + PREF_MODEL, + PREF_HISTORY_ENABLED, + PREF_PRIVATE_BROWSING, + ]) { if (Services.prefs.prefHasUserValue(pref)) { Services.prefs.clearUserPref(pref); } @@ -257,78 +265,177 @@ add_task(function test_cleanInferenceOutput() { /** * Tests for createNewTabPromptGenerator generating prompts based on tab count */ -add_task(async function test_createNewTabPromptGenerator() { - const sb = sinon.createSandbox(); - const writingPrompts = [ - "Write a first draft", - "Improve writing", - "Proofread a message", - ]; +add_task( + async function test_createNewTabPromptGenerator_with_history_enabled() { + const sb = sinon.createSandbox(); + const writingPrompts = [ + "Write a first draft", + "Improve writing", + "Proofread a message", + ]; - const planningPrompts = [ - "Simplify a topic", - "Brainstorm ideas", - "Help make a plan", - ]; - try { - const cases = [ - { - input: { tabCount: -1 }, - expectedBrowsing: ["Find tabs in history"], - }, - { - input: { tabCount: 0 }, - expectedBrowsing: ["Find tabs in history"], - }, - { - input: { tabCount: 1 }, - expectedBrowsing: ["Find tabs in history", "Summarize tabs"], - }, - { - input: { tabCount: 2 }, - expectedBrowsing: [ - "Find tabs in history", - "Summarize tabs", - "Compare tabs", - ], - }, - { - input: { tabCount: 3 }, - expectedBrowsing: [ - "Find tabs in history", - "Summarize tabs", - "Compare tabs", - ], - }, + const planningPrompts = [ + "Simplify a topic", + "Brainstorm ideas", + "Help make a plan", ]; - const promptGenerator = NewTabStarterGenerator; - for (const { input, expectedBrowsing } of cases) { - const results = await promptGenerator.getPrompts(input.tabCount); - Assert.equal(results.length, 3, "Should return 3 suggestions"); - for (const result of results) { - Assert.equal( - result.type, - "chat", - "Each result should have type 'chat'" + try { + const cases = [ + { + input: { tabCount: -1 }, + expectedBrowsing: [], + }, + { + input: { tabCount: 0 }, + expectedBrowsing: ["Find tabs in history"], + }, + { + input: { tabCount: 1 }, + expectedBrowsing: ["Find tabs in history", "Summarize tabs"], + }, + { + input: { tabCount: 2 }, + expectedBrowsing: [ + "Find tabs in history", + "Summarize tabs", + "Compare tabs", + ], + }, + { + input: { tabCount: 3 }, + expectedBrowsing: [ + "Find tabs in history", + "Summarize tabs", + "Compare tabs", + ], + }, + ]; + const promptGenerator = NewTabStarterGenerator; + for (const { input, expectedBrowsing } of cases) { + const results = await promptGenerator.getPrompts(input.tabCount); + if (input.tabCount <= -1) { + Assert.equal(results.length, 2, "Should return 2 suggestions"); + } else { + Assert.equal(results.length, 3, "Should return 3 suggestions"); + } + for (const result of results) { + Assert.equal( + result.type, + "chat", + "Each result should have type 'chat'" + ); + } + Assert.ok( + writingPrompts.includes(results[0].text), + "Results should include a valid writing prompt" + ); + Assert.ok( + planningPrompts.includes(results[1].text), + "Results should include a valid planning prompt" ); + if (results[2]) { + Assert.ok( + expectedBrowsing.includes(results[2].text), + "Results should include a valid browsing prompt" + ); + } } - Assert.ok( - writingPrompts.includes(results[0].text), - "Results should include a valid writing prompt" - ); - Assert.ok( - planningPrompts.includes(results[1].text), - "Results should include a valid planning prompt" - ); - Assert.ok( - expectedBrowsing.includes(results[2].text), - "Results should include a valid browsing prompt" - ); + } finally { + sb.restore(); } - } finally { - sb.restore(); } -}); +); + +/** + * Tests for createNewTabPromptGenerator generating prompts based on tab count, with history disabled + */ +add_task( + async function test_createNewTabPromptGenerator_with_history_disabled() { + const sb = sinon.createSandbox(); + const writingPrompts = [ + "Write a first draft", + "Improve writing", + "Proofread a message", + ]; + + const planningPrompts = [ + "Simplify a topic", + "Brainstorm ideas", + "Help make a plan", + ]; + try { + const cases = [ + { + input: { tabCount: -1 }, + expectedBrowsing: [], + }, + { + input: { tabCount: 0 }, + expectedBrowsing: [], + }, + { + input: { tabCount: 1 }, + expectedBrowsing: ["Summarize tabs"], + }, + { + input: { tabCount: 2 }, + expectedBrowsing: ["Summarize tabs", "Compare tabs"], + }, + { + input: { tabCount: 3 }, + expectedBrowsing: ["Summarize tabs", "Compare tabs"], + }, + ]; + for (const pref of [ + [{ key: PREF_HISTORY_ENABLED, value: false }], + [{ key: PREF_PRIVATE_BROWSING, value: true }], + [ + { key: PREF_HISTORY_ENABLED, value: false }, + { key: PREF_PRIVATE_BROWSING, value: true }, + ], + ]) { + for (const p of pref) { + Services.prefs.setBoolPref(p.key, p.value); + } + const promptGenerator = NewTabStarterGenerator; + for (const { input, expectedBrowsing } of cases) { + const results = await promptGenerator.getPrompts(input.tabCount); + if (input.tabCount <= 0) { + Assert.equal(results.length, 2, "Should return 2 suggestions"); + } else { + Assert.equal(results.length, 3, "Should return 3 suggestions"); + } + for (const result of results) { + Assert.equal( + result.type, + "chat", + "Each result should have type 'chat'" + ); + } + Assert.ok( + writingPrompts.includes(results[0].text), + "Results should include a valid writing prompt" + ); + Assert.ok( + planningPrompts.includes(results[1].text), + "Results should include a valid planning prompt" + ); + if (results[2]) { + Assert.ok( + expectedBrowsing.includes(results[2].text), + "Results should include a valid browsing prompt" + ); + } + } + for (const p of pref) { + Services.prefs.clearUserPref(p.key); + } + } + } finally { + sb.restore(); + } + } +); /** * Tests for generateConversationStartersSidebar successfully generating suggestions