commit 4e1d5ad706a238ce6e47afc444edef1f83955662
parent fdc8f4dba119903c206a6115035a8f4a95debfd9
Author: Yubin Jamora <yjamora@mozilla.com>
Date: Mon, 1 Dec 2025 23:26:17 +0000
Bug 2000910 - remove prompt after auto submit in chatbot r=Mardak,ai-frontend-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D273082
Diffstat:
3 files changed, 67 insertions(+), 16 deletions(-)
diff --git a/browser/components/genai/GenAIChild.sys.mjs b/browser/components/genai/GenAIChild.sys.mjs
@@ -230,14 +230,33 @@ export class GenAIChild extends JSWindowActorChild {
(/chatgpt\.com/i.test(win.location.host) ||
win.location.pathname.includes("file_chat-autosubmit.html"))
) {
- win.setTimeout(() => {
- if (editable.textContent) {
- editable.textContent = "";
- editable.dispatchEvent(
+ const container = editable.parentElement;
+ if (!container) {
+ return;
+ }
+
+ const observer = new win.MutationObserver(() => {
+ // Always refetch because ChatGPT replaces editable div
+ const currentEditable = container.querySelector(
+ '[contenteditable="true"]'
+ );
+ if (!currentEditable) {
+ return;
+ }
+
+ let hasText = currentEditable.textContent?.trim().length > 0;
+ if (hasText) {
+ currentEditable.textContent = "";
+ currentEditable.dispatchEvent(
new win.InputEvent("input", { bubbles: true })
);
}
- }, 500);
+ });
+
+ observer.observe(container, { childList: true, subtree: true });
+
+ // Disconnect once things stabilize
+ win.setTimeout(() => observer.disconnect(), 2000);
}
}
diff --git a/browser/components/genai/tests/browser/browser_chat_request.js b/browser/components/genai/tests/browser/browser_chat_request.js
@@ -136,15 +136,24 @@ add_task(async function test_chat_auto_submit() {
1,
"Form is triggered by AutoSubmitClick"
);
+ });
- await ContentTaskUtils.waitForCondition(
- () => content.document.getElementById("ta").textContent === "",
- "Prompt was cleared"
- );
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
+ await ContentTaskUtils.waitForCondition(() => {
+ const editable = content.document.querySelector(
+ '[contenteditable="true"]'
+ );
+
+ return editable && editable.textContent.trim() === "";
+ }, "Prompt text was cleared by MutationObserver");
+ });
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
+ const editable = content.document.querySelector('[contenteditable="true"]');
Assert.equal(
- content.document.getElementById("ta").textContent,
+ editable.textContent.trim(),
"",
- "Prompt text is cleared after auto submission"
+ "Prompt text was cleared after auto submission"
);
});
diff --git a/browser/components/genai/tests/browser/file_chat-autosubmit.html b/browser/components/genai/tests/browser/file_chat-autosubmit.html
@@ -9,14 +9,37 @@
<script>
const url = new URL(location.href);
const prompt = url.searchParams.get("q") || "";
- const ta = document.getElementById("ta");
const form = document.getElementById("f");
+
window.submitCount = 0;
- setTimeout(() => {
- ta.textContent = prompt;
- ta.dispatchEvent(new InputEvent("input", { bubbles: true }));
- }, 50);
+ // Simulate ChatGPT's behavior - replace editable div mulitiple time
+ function simulateChatGPTReplacement() {
+ let editable = document.querySelector('[contenteditable="true"]');
+ editable.textContent = prompt;
+
+ editable.dispatchEvent(new InputEvent("input"), { bubbles: true });
+
+ setTimeout(() => {
+ const newDiv = document.createElement("div");
+ newDiv.setAttribute("contenteditable", "true");
+ newDiv.textContent = prompt;
+ editable.replaceWith(newDiv);
+
+ newDiv.dispatchEvent(new InputEvent("input", { bubbles: true }));
+
+ setTimeout(() => {
+ const finalDiv = document.createElement("div");
+ finalDiv.setAttribute("contenteditable", "true");
+ finalDiv.textContent = prompt;
+ newDiv.replaceWith(finalDiv);
+
+ finalDiv.dispatchEvent(new InputEvent("input", { bubbles: true }));
+ }, 50);
+ }, 50);
+ }
+
+ setTimeout(simulateChatGPTReplacement, 50);
form.addEventListener("submit", e => {
e.preventDefault();