commit e7948ea257d143e4f44771d0d2a59b07df9931b1
parent e61551b429cf31beaa4d56c8b159fa4b947b307b
Author: Moritz Beier <mbeier@mozilla.com>
Date: Mon, 24 Nov 2025 10:37:20 +0000
Bug 1983016 - When the old or the new search bar are disabled, ensure they don't have active listeners and observers. r=dao,search-reviewers,urlbar-reviewers,scunnane
Differential Revision: https://phabricator.services.mozilla.com/D272227
Diffstat:
2 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/browser/components/search/content/searchbar.js b/browser/components/search/content/searchbar.js
@@ -49,14 +49,12 @@
constructor() {
super();
-
MozXULElement.insertFTLIfNeeded("browser/search.ftl");
- this.destroy = this.destroy.bind(this);
this._setupEventListeners();
let searchbar = this;
this.observer = {
- observe(aEngine, aTopic) {
+ observe(aEngine, aTopic, aData) {
if (aTopic == "browser-search-engine-modified") {
// Make sure the engine list is refetched next time it's needed
searchbar._engines = null;
@@ -64,19 +62,41 @@
// Update the popup header and update the display after any modification.
searchbar._textbox.popup.updateHeader();
searchbar.updateDisplay();
+ } else if (
+ aData == "browser.search.widget.new" &&
+ searchbar.isConnected
+ ) {
+ if (Services.prefs.getBoolPref("browser.search.widget.new")) {
+ searchbar.disconnectedCallback();
+ } else {
+ searchbar.connectedCallback();
+ }
}
},
QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
};
+ Services.prefs.addObserver("browser.search.widget.new", this.observer);
+
+ window.addEventListener("unload", () => {
+ this.destroy();
+ Services.prefs.removeObserver(
+ "browser.search.widget.new",
+ this.observer
+ );
+ });
+
this._ignoreFocus = false;
this._engines = null;
this.telemetrySelectedIndex = -1;
}
connectedCallback() {
- // Don't initialize if this isn't going to be visible
- if (this.closest("#BrowserToolbarPalette")) {
+ // Don't initialize if this isn't going to be visible.
+ if (
+ this.closest("#BrowserToolbarPalette") ||
+ Services.prefs.getBoolPref("browser.search.widget.new")
+ ) {
return;
}
@@ -108,8 +128,6 @@
this._setupTextboxEventListeners();
this._initTextbox();
- window.addEventListener("unload", this.destroy);
-
Services.obs.addObserver(this.observer, "browser-search-engine-modified");
this._initialized = true;
@@ -225,7 +243,6 @@
destroy() {
if (this._initialized) {
this._initialized = false;
- window.removeEventListener("unload", this.destroy);
Services.obs.removeObserver(
this.observer,
diff --git a/browser/components/urlbar/content/UrlbarInput.mjs b/browser/components/urlbar/content/UrlbarInput.mjs
@@ -235,6 +235,11 @@ export class UrlbarInput extends HTMLElement {
this.isPrivate = lazy.PrivateBrowsingUtils.isWindowPrivate(this.window);
lazy.UrlbarPrefs.addObserver(this);
+ window.addEventListener("unload", () => {
+ // Stop listening to pref changes to make sure we don't init the new
+ // searchbar in closed windows that have not been gc'd yet.
+ lazy.UrlbarPrefs.removeObserver(this);
+ });
}
/**
@@ -275,7 +280,7 @@ export class UrlbarInput extends HTMLElement {
/**
* Initialization that happens once on the first connect.
*/
- #init() {
+ #initOnce() {
this.#sapName = this.getAttribute("sap-name");
this.#isAddressbar = this.#sapName == "urlbar";
@@ -350,8 +355,19 @@ export class UrlbarInput extends HTMLElement {
}
connectedCallback() {
+ if (
+ this.sapName == "searchbar" &&
+ !lazy.UrlbarPrefs.get("browser.search.widget.new")
+ ) {
+ return;
+ }
+
+ this.#init();
+ }
+
+ #init() {
if (!this.controller) {
- this.#init();
+ this.#initOnce();
}
// Don't attach event listeners if the toolbar is not visible
@@ -433,8 +449,21 @@ export class UrlbarInput extends HTMLElement {
}
disconnectedCallback() {
- this.inputField.controllers.removeController(this._copyCutController);
- delete this._copyCutController;
+ if (
+ this.sapName == "searchbar" &&
+ !lazy.UrlbarPrefs.get("browser.search.widget.new")
+ ) {
+ return;
+ }
+
+ this.#uninit();
+ }
+
+ #uninit() {
+ if (this._copyCutController) {
+ this.inputField.controllers.removeController(this._copyCutController);
+ delete this._copyCutController;
+ }
for (let event of UrlbarInput.#inputFieldEvents) {
this.inputField.removeEventListener(event, this);
@@ -562,12 +591,14 @@ export class UrlbarInput extends HTMLElement {
);
break;
case "browser.search.widget.new": {
- if (
- this.#sapName == "searchbar" &&
- lazy.UrlbarPrefs.get("browser.search.widget.new")
- ) {
- // Update dimensions because the searchbar was invisible before.
- this.#updateLayoutBreakout();
+ if (this.sapName == "searchbar" && this.isConnected) {
+ if (lazy.UrlbarPrefs.get("browser.search.widget.new")) {
+ // The connectedCallback was skipped. Init now.
+ this.#init();
+ } else {
+ // Uninit now, the disconnectedCallback will be skipped.
+ this.#uninit();
+ }
}
}
}
@@ -3847,6 +3878,9 @@ export class UrlbarInput extends HTMLElement {
}
_initCopyCutController() {
+ if (this._copyCutController) {
+ return;
+ }
this._copyCutController = new CopyCutController(this);
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
}