commit d2cc7af77543c2e0fc3a80a7b5e9dfe063f7da02
parent c290a3bc9ad0374a8255fec7a954eba5d6bf2773
Author: James Teow <jteow@mozilla.com>
Date: Wed, 19 Nov 2025 19:12:32 +0000
Bug 1983398 - Set pageproxystate to invalid when sanitizing pasted content - r=urlbar-reviewers,daisuke
Differential Revision: https://phabricator.services.mozilla.com/D272376
Diffstat:
3 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/browser/components/urlbar/content/UrlbarInput.mjs b/browser/components/urlbar/content/UrlbarInput.mjs
@@ -5045,6 +5045,13 @@ export class UrlbarInput extends HTMLElement {
this._setValue(value, { valueIsTyped: true });
this.userTypedValue = value;
+ // Since we prevent the default paste event, we have to ensure the
+ // pageproxystate is updated. The paste event replaces the actual current
+ // page's URL with user-typed content, so we should set pageproxystate to
+ // invalid.
+ if (this.getAttribute("pageproxystate") == "valid") {
+ this.setPageProxyState("invalid");
+ }
this.toggleAttribute("usertyping", this._untrimmedValue);
// Fix up cursor/selection:
diff --git a/browser/components/urlbar/tests/browser/browser_paste_multi_lines.js b/browser/components/urlbar/tests/browser/browser_paste_multi_lines.js
@@ -208,6 +208,32 @@ add_task(async function test_paste_after_opening_autocomplete_panel() {
}
});
+add_task(async function test_paste_onto_urlbar_on_website() {
+ // Deliberately use a page that is not about:blank to ensure that
+ // we correctly handle pasting while on a real webpage. We also use
+ // mochi.test to avoid any interfering with tests that use example.com.
+ let loaded = BrowserTestUtils.browserLoaded(
+ gBrowser.selectedBrowser,
+ false,
+ "http://mochi.test:8888/"
+ );
+ BrowserTestUtils.startLoadingURIString(
+ gBrowser.selectedBrowser,
+ "http://mochi.test:8888/"
+ );
+ await loaded;
+
+ for (const { input, expected } of TEST_DATA) {
+ gURLBar.handleRevert();
+ gURLBar.select();
+
+ await paste(input);
+ await assertResult(expected);
+
+ await UrlbarTestUtils.promisePopupClose(window);
+ }
+});
+
async function assertResult(expected) {
Assert.equal(gURLBar.value, expected.urlbar, "Pasted value is correct");
Assert.ok(gURLBar.valueIsTyped, "Pasted value counts as typed.");
@@ -225,6 +251,11 @@ async function assertResult(expected) {
BrowserTestUtils.isVisible(gURLBar.goButton),
"Go button should be visible"
);
+ Assert.equal(
+ gURLBar.getAttribute("pageproxystate"),
+ "invalid",
+ "Pageproxystate is invalid"
+ );
} else {
Assert.ok(
!gURLBar.hasAttribute("usertyping"),
diff --git a/browser/components/urlbar/tests/browser/browser_revert.js b/browser/components/urlbar/tests/browser/browser_revert.js
@@ -31,3 +31,51 @@ add_task(async function () {
}
);
});
+
+// Tests that pasting a multi-line string into the address bar and reverting
+// it works as expected.
+add_task(async function paste_and_revert() {
+ registerCleanupFunction(async () => {
+ SpecialPowers.clipboardCopyString("");
+ await PlacesUtils.history.clear();
+ });
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: "https://example.com",
+ },
+ async function () {
+ gURLBar.value = "";
+ gURLBar.focus();
+
+ let input = "https://exam\n";
+ await SimpleTest.promiseClipboardChange(input, () => {
+ clipboardHelper.copyString(input);
+ });
+ document.commandDispatcher
+ .getControllerForCommand("cmd_paste")
+ .doCommand("cmd_paste");
+
+ Assert.equal(
+ gURLBar.value,
+ "https://exam",
+ "Location bar has the pasted value."
+ );
+
+ gURLBar.focus();
+ EventUtils.synthesizeKey("KEY_Escape");
+ EventUtils.synthesizeKey("KEY_Escape");
+
+ Assert.equal(
+ gURLBar.value,
+ "example.com",
+ "Location bar has the reverted value."
+ );
+ Assert.equal(
+ gURLBar.getAttribute("pageproxystate"),
+ "valid",
+ "Pageproxystate is valid after revert."
+ );
+ }
+ );
+});