commit 2c4f7ccc297e53f50489ef591763c1dbcab7cb2f
parent 99a822346241d9938df5016f6738f0976def21c3
Author: Yubin Jamora <yjamora@mozilla.com>
Date: Fri, 9 Jan 2026 21:26:34 +0000
Bug 2006250 -Add AI Window section within AI Features about:preferences r=mstriemer,fluent-reviewers,flod
Differential Revision: https://phabricator.services.mozilla.com/D277455
Diffstat:
5 files changed, 151 insertions(+), 11 deletions(-)
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
@@ -2275,6 +2275,7 @@ pref("browser.aiwindow.memoriesLogLevel", "Warn");
pref("browser.aiwindow.firstrun.autoAdvanceMS", 3000);
pref("browser.aiwindow.firstrun.modelChoice", "");
pref("browser.aiwindow.model", "qwen3-235b-a22b-instruct-2507-maas");
+pref("browser.aiwindow.preferences.enabled", false);
// Block insecure active content on https pages
pref("security.mixed_content.block_active_content", true);
diff --git a/browser/components/preferences/config/aiFeatures.mjs b/browser/components/preferences/config/aiFeatures.mjs
@@ -12,7 +12,11 @@ const lazy = XPCOMUtils.declareLazy({
GenAI: "resource:///modules/GenAI.sys.mjs",
});
-Preferences.addAll([{ id: "browser.ml.chat.provider", type: "string" }]);
+Preferences.addAll([
+ { id: "browser.ml.chat.provider", type: "string" },
+ { id: "browser.aiwindow.enabled", type: "bool" },
+ { id: "browser.aiwindow.preferences.enabled", type: "bool" },
+]);
Preferences.addSetting({ id: "chatbotProviderItem" });
Preferences.addSetting({
@@ -50,6 +54,39 @@ Preferences.addSetting({
},
});
+Preferences.addSetting({
+ id: "AIWindowEnabled",
+ pref: "browser.aiwindow.enabled",
+});
+
+Preferences.addSetting({
+ id: "AIWindowPreferencesEnabled",
+ pref: "browser.aiwindow.preferences.enabled",
+});
+
+// Only show the feature settings if the prefs are allowed to show and the
+// feature isn't enabled.
+Preferences.addSetting({
+ id: "AIWindowItem",
+ deps: ["AIWindowEnabled", "AIWindowPreferencesEnabled"],
+ visible: deps => {
+ return deps.AIWindowPreferencesEnabled.value && !deps.AIWindowEnabled.value;
+ },
+});
+Preferences.addSetting({ id: "AIWindowHeader" });
+Preferences.addSetting({ id: "AIWindowActivateLink" });
+
+// Only show the AI Window features if the prefs are allowed to show and the
+// feature is enabled.
+// TODO: Enable when Model and Insight options are added
+Preferences.addSetting({
+ id: "aiFeaturesAIWindowGroup",
+ deps: ["AIWindowEnabled", "AIWindowPreferencesEnabled"],
+ visible: deps => {
+ return deps.AIWindowPreferencesEnabled.value && deps.AIWindowEnabled.value;
+ },
+});
+
SettingGroupManager.registerGroups({
aiFeatures: {
l10nId: "try-ai-features-group",
@@ -72,6 +109,35 @@ SettingGroupManager.registerGroups({
},
],
},
+ {
+ id: "AIWindowItem",
+ control: "moz-box-group",
+ items: [
+ {
+ id: "AIWindowHeader",
+ l10nId: "try-ai-features-ai-window",
+ control: "moz-box-item",
+ },
+ {
+ id: "AIWindowActivateLink",
+ l10nId: "try-ai-features-ai-window-activate-link",
+ control: "moz-box-link",
+ },
+ ],
+ },
+ ],
+ },
+ aiWindowFeatures: {
+ l10nId: "ai-window-features-group",
+ headingLevel: 2,
+ items: [
+ {
+ id: "aiFeaturesAIWindowGroup",
+ control: "moz-box-group",
+ // TODO: Add Model and Insight list
+ // options: [
+ // ],
+ },
],
},
});
diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js
@@ -281,7 +281,7 @@ const CONFIG_PANES = Object.freeze({
},
aiFeatures: {
l10nId: "preferences-ai-features-header",
- groupIds: ["aiFeatures"],
+ groupIds: ["aiFeatures", "aiWindowFeatures"],
module: "chrome://browser/content/preferences/config/aiFeatures.mjs",
visible: () => srdSectionEnabled("aiFeatures"),
},
diff --git a/browser/components/preferences/tests/browser_aiFeatures.js b/browser/components/preferences/tests/browser_aiFeatures.js
@@ -8,10 +8,7 @@ describe("settings ai features", () => {
beforeEach(async function setup() {
await SpecialPowers.pushPrefEnv({
- set: [
- ["browser.ml.chat.provider", ""],
- ["browser.settings-redesign.aiFeatures.enabled", true],
- ],
+ set: [["browser.settings-redesign.aiFeatures.enabled", true]],
});
await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
doc = gBrowser.selectedBrowser.contentDocument;
@@ -20,10 +17,21 @@ describe("settings ai features", () => {
afterEach(() => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
- gBrowser.ownerGlobal.SidebarController.hide();
});
+ async function openAiFeaturePanel() {
+ const paneLoaded = waitForPaneChange("aiFeatures");
+ const categoryButton = doc.getElementById("category-ai-features");
+ categoryButton.scrollIntoView();
+ EventUtils.synthesizeMouseAtCenter(categoryButton, {}, win);
+ await paneLoaded;
+ }
+
it("can change the chatbot provider value", async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.ml.chat.provider", ""]],
+ });
+
const categoryButton = doc.getElementById("category-ai-features");
Assert.ok(categoryButton, "category exists");
Assert.ok(
@@ -31,10 +39,7 @@ describe("settings ai features", () => {
"category is visible"
);
- const paneLoaded = waitForPaneChange("aiFeatures");
- categoryButton.scrollIntoView();
- EventUtils.synthesizeMouseAtCenter(categoryButton, {}, win);
- await paneLoaded;
+ await openAiFeaturePanel();
const providerControl = doc.getElementById("chatbotProvider");
Assert.ok(providerControl, "control exists");
@@ -67,5 +72,63 @@ describe("settings ai features", () => {
"",
"Pref is not empty"
);
+
+ await gBrowser.ownerGlobal.SidebarController.hide();
+ });
+
+ it("hides AI Window when preferences not enabled", async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.aiwindow.preferences.enabled", false]],
+ });
+
+ await openAiFeaturePanel();
+
+ const aiWindowItem = doc.getElementById("AIWindowItem");
+ const aiWindowFeatures = doc.getElementById("aiFeaturesAIWindowGroup");
+
+ Assert.ok(
+ !BrowserTestUtils.isVisible(aiWindowItem),
+ "AIWindowItem is hidden when preferences not enabled"
+ );
+ Assert.ok(
+ !BrowserTestUtils.isVisible(aiWindowFeatures),
+ "aiWindowFeatures is hidden when preferences not enabled"
+ );
+ });
+
+ it("shows AI Window activate when preferences enabled and feature not enabled", async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.aiwindow.preferences.enabled", true],
+ ["browser.aiwindow.enabled", false],
+ ],
+ });
+
+ await openAiFeaturePanel();
+
+ const aiWindowItem = doc.getElementById("AIWindowItem");
+ Assert.ok(
+ BrowserTestUtils.isVisible(aiWindowItem),
+ "AIWindowItem is visible when preferences enabled and feature not enabled"
+ );
+ });
+
+ it("hides AI Window activate when feature enabled", async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.aiwindow.preferences.enabled", true],
+ ["browser.aiwindow.enabled", true],
+ ],
+ });
+
+ await openAiFeaturePanel();
+
+ const aiWindowItem = doc.getElementById("AIWindowItem");
+ Assert.ok(
+ !BrowserTestUtils.isVisible(aiWindowItem),
+ "AIWindowItem is hidden when feature enabled"
+ );
});
+
+ // TODO: Add tests for aiFeaturesAIWindowGroup when Model and Insight options are added
});
diff --git a/browser/locales-preview/aiFeatures.ftl b/browser/locales-preview/aiFeatures.ftl
@@ -19,3 +19,13 @@ try-ai-features-chatbot-provider =
# This labels the unset option for AI Chatbot selection, the other options are brand names like "ChatGPT" and "Anthropic Claude"
try-ai-features-chatbot-choose-label =
.label = Choose provider
+
+try-ai-features-ai-window =
+ .label = AI Window
+ .description = A separate window that learns as you browse. Get quick answers about your tabs and a more personalized experience.
+try-ai-features-ai-window-activate-link =
+ .label = Activate AI Window
+
+ai-window-features-group =
+ .label = AI Window
+ .description = Choose which model powers the assistant and control what AI Window learns from your activity.