summaryrefslogtreecommitdiffstats
path: root/browser/components/customizableui/SearchWidgetTracker.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/customizableui/SearchWidgetTracker.sys.mjs')
-rw-r--r--browser/components/customizableui/SearchWidgetTracker.sys.mjs118
1 files changed, 118 insertions, 0 deletions
diff --git a/browser/components/customizableui/SearchWidgetTracker.sys.mjs b/browser/components/customizableui/SearchWidgetTracker.sys.mjs
new file mode 100644
index 0000000000..64d7720349
--- /dev/null
+++ b/browser/components/customizableui/SearchWidgetTracker.sys.mjs
@@ -0,0 +1,118 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Keeps the "browser.search.widget.inNavBar" preference synchronized,
+ * and ensures persisted widths are updated if the search bar is removed.
+ */
+
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+import { CustomizableUI } from "resource:///modules/CustomizableUI.sys.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineModuleGetter(
+ lazy,
+ "BrowserUsageTelemetry",
+ "resource:///modules/BrowserUsageTelemetry.jsm"
+);
+
+const WIDGET_ID = "search-container";
+const PREF_NAME = "browser.search.widget.inNavBar";
+
+export const SearchWidgetTracker = {
+ init() {
+ this.onWidgetReset = this.onWidgetUndoMove = node => {
+ if (node.id == WIDGET_ID) {
+ this.syncPreferenceWithWidget();
+ this.removePersistedWidths();
+ }
+ };
+ CustomizableUI.addListener(this);
+ Services.prefs.addObserver(PREF_NAME, () =>
+ this.syncWidgetWithPreference()
+ );
+ },
+
+ onWidgetAdded(widgetId, area) {
+ if (widgetId == WIDGET_ID && area == CustomizableUI.AREA_NAVBAR) {
+ this.syncPreferenceWithWidget();
+ }
+ },
+
+ onWidgetRemoved(aWidgetId, aArea) {
+ if (aWidgetId == WIDGET_ID && aArea == CustomizableUI.AREA_NAVBAR) {
+ this.syncPreferenceWithWidget();
+ this.removePersistedWidths();
+ }
+ },
+
+ onAreaNodeRegistered(aArea) {
+ // The placement of the widget always takes priority, and the preference
+ // should always match the actual placement when the browser starts up - i.e.
+ // once the navigation bar has been registered.
+ if (aArea == CustomizableUI.AREA_NAVBAR) {
+ this.syncPreferenceWithWidget();
+ }
+ },
+
+ onCustomizeEnd() {
+ // onWidgetUndoMove does not fire when the search container is moved back to
+ // the customization palette as a result of an undo, so we sync again here.
+ this.syncPreferenceWithWidget();
+ },
+
+ syncPreferenceWithWidget() {
+ Services.prefs.setBoolPref(PREF_NAME, this.widgetIsInNavBar);
+ },
+
+ syncWidgetWithPreference() {
+ let newValue = Services.prefs.getBoolPref(PREF_NAME);
+ if (newValue == this.widgetIsInNavBar) {
+ return;
+ }
+
+ if (newValue) {
+ // The URL bar widget is always present in the navigation toolbar, so we
+ // can simply read its position to place the search bar right after it.
+ CustomizableUI.addWidgetToArea(
+ WIDGET_ID,
+ CustomizableUI.AREA_NAVBAR,
+ CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1
+ );
+ lazy.BrowserUsageTelemetry.recordWidgetChange(
+ WIDGET_ID,
+ CustomizableUI.AREA_NAVBAR,
+ "searchpref"
+ );
+ } else {
+ CustomizableUI.removeWidgetFromArea(WIDGET_ID);
+ lazy.BrowserUsageTelemetry.recordWidgetChange(
+ WIDGET_ID,
+ null,
+ "searchpref"
+ );
+ }
+ },
+
+ removePersistedWidths() {
+ Services.xulStore.removeValue(
+ AppConstants.BROWSER_CHROME_URL,
+ WIDGET_ID,
+ "width"
+ );
+ for (let win of CustomizableUI.windows) {
+ let searchbar =
+ win.document.getElementById(WIDGET_ID) ||
+ win.gNavToolbox.palette.querySelector("#" + WIDGET_ID);
+ searchbar.removeAttribute("width");
+ searchbar.style.removeProperty("width");
+ }
+ },
+
+ get widgetIsInNavBar() {
+ let placement = CustomizableUI.getPlacementOfWidget(WIDGET_ID);
+ return placement?.area == CustomizableUI.AREA_NAVBAR;
+ },
+};