Bug 1417155 - Add new Home/New Tab page section to about:prefs#home draft
authork88hudson <k88hudson@gmail.com>
Thu, 08 Mar 2018 10:54:53 -0500
changeset 769629 fa511dadfb141381089814ebea5a0d8001f080fc
parent 769628 a3acbd92ba4f76cc72c44a26923e6ec8a857f1e3
push id103195
push userbmo:khudson@mozilla.com
push dateMon, 19 Mar 2018 21:52:37 +0000
bugs1417155
milestone61.0a1
Bug 1417155 - Add new Home/New Tab page section to about:prefs#home MozReview-Commit-ID: 4ip7irrfLbR
browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js
browser/components/preferences/in-content/home.js
browser/components/preferences/in-content/home.xul
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/main.xul
browser/components/preferences/in-content/preferences.xul
browser/components/preferences/in-content/tests/browser_extension_controlled.js
browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_1.js
browser/components/preferences/in-content/tests/browser_search_within_preferences_1.js
browser/locales/en-US/browser/preferences/preferences.ftl
browser/themes/shared/incontentprefs/preferences.inc.css
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js
@@ -152,19 +152,24 @@ add_task(async function homepage_test_lo
   is(Services.prefs.prefIsLocked("browser.startup.page"), true,
      "Start page type pref should be locked");
 
   // Test that UI is disabled when the Locked property is enabled
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
   await ContentTask.spawn(tab.linkedBrowser, null, async function() {
     is(content.document.getElementById("browserStartupPage").disabled, true,
        "When homepage is locked, the startup page choice controls should be locked");
-    is(content.document.getElementById("browserHomePage").disabled, true,
-       "Homepage input should be disabled");
-    is(content.document.getElementById("useCurrent").disabled, true,
+  });
+  await BrowserTestUtils.loadURI(tab.linkedBrowser, "about:preferences#home");
+  await ContentTask.spawn(tab.linkedBrowser, null, async function() {
+    is(content.document.getElementById("homeMode").disabled, true,
+       "Homepage menulist should be disabled");
+    is(content.document.getElementById("homePageUrl").disabled, true,
+       "Homepage custom input should be disabled");
+    is(content.document.getElementById("useCurrentBtn").disabled, true,
        "\"Use Current Page\" button should be disabled");
-    is(content.document.getElementById("useBookmark").disabled, true,
+    is(content.document.getElementById("useBookmarkBtn").disabled, true,
        "\"Use Bookmark...\" button should be disabled");
-    is(content.document.getElementById("restoreDefaultHomePage").disabled, true,
+    is(content.document.getElementById("restoreDefaultHomePageBtn").disabled, true,
        "\"Restore to Default\" button should be disabled");
   });
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/preferences/in-content/home.js
+++ b/browser/components/preferences/in-content/home.js
@@ -1,7 +1,337 @@
 /* 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/. */
 
+ /* import-globals-from extensionControlled.js */
+ /* import-globals-from preferences.js */
+
+ // HOME PAGE
+
+ /*
+   * Preferences:
+   *
+   * browser.startup.homepage
+   * - the user's home page, as a string; if the home page is a set of tabs,
+   *   this will be those URLs separated by the pipe character "|"
+   * browser.newtabpage.enabled
+   * - determines that is shown on the user's new tab page.
+   *   true = Activity Stream is shown,
+   *   false = about:blank is shown
+   */
+
+Preferences.addAll([
+  { id: "browser.startup.homepage", type: "wstring" },
+  { id: "pref.browser.homepage.disable_button.current_page", type: "bool" },
+  { id: "pref.browser.homepage.disable_button.bookmark_page", type: "bool" },
+  { id: "pref.browser.homepage.disable_button.restore_default", type: "bool" },
+  { id: "browser.newtabpage.enabled", type: "bool" }
+]);
+
+const HOMEPAGE_OVERRIDE_KEY = "homepage_override";
+const URL_OVERRIDES_TYPE = "url_overrides";
+const NEW_TAB_KEY = "newTabURL";
+const NEW_TAB_STRING_ID = "extensionControlled.newTabURL2";
+
 let gHomePane = {
-  init() {}
+  HOME_MODE_FIREFOX_HOME: "0",
+  HOME_MODE_BLANK: "1",
+  HOME_MODE_CUSTOM: "2",
+  NEWTAB_ENABLED_PREF: "browser.newtabpage.enabled",
+
+  /**
+   * _handleNewTabOverrides: disables new tab settings UI. Called by
+   * an observer in ._watchNewTab that watches for new tab url changes
+   */
+  async _handleNewTabOverrides() {
+    const isControlled = await handleControllingExtension(
+      URL_OVERRIDES_TYPE, NEW_TAB_KEY, NEW_TAB_STRING_ID);
+    const el = document.getElementById("newTabMode");
+    el.disabled = isControlled;
+  },
+
+  /**
+   * watchNewTab: Listen for changes to the new tab url and disable appropriate
+   * areas of the UI
+   */
+  watchNewTab() {
+    this._handleNewTabOverrides();
+    let newTabObserver = {
+      observe: this._handleNewTabOverrides.bind(this)
+    };
+    Services.obs.addObserver(newTabObserver, "newtab-url-changed");
+    window.addEventListener("unload", () => {
+      Services.obs.removeObserver(newTabObserver, "newtab-url-changed");
+    });
+  },
+
+  /**
+   * _renderCustomSettings: Hides or shows the UI for setting a custom
+   * homepage URL
+   * @param {bool} shouldShow Should the custom UI be shown?
+   */
+  _renderCustomSettings(shouldShow) {
+    const customSettingsContainerEl = document.getElementById("customSettings");
+    const customUrlEl = document.getElementById("homePageUrl");
+    const isHomepageCustom = !this._isHomePageDefaultValue() && !this._isHomePageBlank();
+    if (typeof shouldShow === "undefined") shouldShow = isHomepageCustom;
+
+    customSettingsContainerEl.hidden = !shouldShow;
+    if (isHomepageCustom) {
+      customUrlEl.value = Preferences.get("browser.startup.homepage").value;
+    } else {
+      customUrlEl.value = "";
+    }
+  },
+
+  /**
+   * _isHomePageDefaultValue
+   * @returns {bool} Is the homepage set to the default pref value?
+   */
+  _isHomePageDefaultValue() {
+    const homePref = Preferences.get("browser.startup.homepage");
+    return homePref.value === homePref.defaultValue;
+  },
+
+  /**
+   * _isHomePageBlank
+   * @returns {bool} Is the homepage set to about:blank?
+   */
+  _isHomePageBlank() {
+    const homePref = Preferences.get("browser.startup.homepage");
+    return homePref.value === "about:blank" || homePref.value === "";
+  },
+
+  /**
+   * _isTabAboutPreferences: Is a given tab set to about:preferences?
+   * @param {Element} aTab A tab element
+   * @returns {bool} Is the linkedBrowser of aElement set to about:preferences?
+   */
+  _isTabAboutPreferences(aTab) {
+    return aTab.linkedBrowser.currentURI.spec.startsWith("about:preferences");
+  },
+
+  /**
+   * _getTabsForHomePage
+   * @returns {Array} An array of current tabs
+   */
+  _getTabsForHomePage() {
+    let tabs = [];
+    let win = Services.wm.getMostRecentWindow("navigator:browser");
+
+    // We should only include visible & non-pinned tabs
+    if (win && win.document.documentElement.getAttribute("windowtype") === "navigator:browser") {
+      tabs = win.gBrowser.visibleTabs.slice(win.gBrowser._numPinnedTabs);
+      tabs = tabs.filter(tab => !this._isTabAboutPreferences(tab));
+      // XXX: Bug 1441637 - Fix tabbrowser to report tab.closing before it blurs it
+      tabs = tabs.filter(tab => !tab.closing);
+    }
+
+    return tabs;
+  },
+
+  _renderHomepageMode() {
+    const isDefault = this._isHomePageDefaultValue();
+    const isBlank = this._isHomePageBlank();
+    const el = document.getElementById("homeMode");
+
+    if (isDefault) {
+      el.value = this.HOME_MODE_FIREFOX_HOME;
+    } else if (isBlank) {
+      el.value = this.HOME_MODE_BLANK;
+    } else {
+      el.value = this.HOME_MODE_CUSTOM;
+    }
+  },
+
+  _setInputDisabledStates(isControlled) {
+    let tabCount = this._getTabsForHomePage().length;
+
+    // Disable or enable the inputs based on if this is controlled by an extension.
+    document.querySelectorAll(".check-home-page-controlled")
+      .forEach((element) => {
+        let isDisabled;
+        let pref = element.getAttribute("preference") || element.getAttribute("data-preference-related");
+        if (!pref) {
+          throw new Error(`Element with id ${element.id} did not have preference or data-preference-related attribute defined.`);
+        }
+        isDisabled = Preferences.get(pref).locked || isControlled;
+
+        if (pref === "pref.browser.disable_button.current_page") {
+          // Special case for current_page to disable it if tabCount is 0
+          isDisabled = isDisabled || tabCount < 1;
+        }
+
+        element.disabled = isDisabled;
+      });
+  },
+
+  async _handleHomePageOverrides() {
+    const homePref = Preferences.get("browser.startup.homepage");
+    if (homePref.locked) {
+      // An extension can't control these settings if they're locked.
+      hideControllingExtension(HOMEPAGE_OVERRIDE_KEY);
+      this._setInputDisabledStates(false);
+    } else {
+      // Asynchronously update the extension controlled UI.
+      const isHomePageControlled = await handleControllingExtension(
+        PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY, "extensionControlled.homepage_override2");
+      this._setInputDisabledStates(isHomePageControlled);
+    }
+  },
+
+  syncFromHomePref() {
+    // Set the "Use Current Page(s)" button's text and enabled state.
+    this._updateUseCurrentButton();
+    this._renderCustomSettings();
+    this._renderHomepageMode();
+    this._handleHomePageOverrides();
+  },
+
+  syncFromNewTabPref() {
+    const newtabPref = Preferences.get(this.NEWTAB_ENABLED_PREF);
+    return newtabPref.value ? this.HOME_MODE_FIREFOX_HOME : this.HOME_MODE_BLANK;
+  },
+
+  syncToNewTabPref(value) {
+    return value !== this.HOME_MODE_BLANK;
+  },
+
+  onMenuChange(event) {
+    const {value} = event.target;
+    const homePref = Preferences.get("browser.startup.homepage");
+    switch (value) {
+      case this.HOME_MODE_FIREFOX_HOME:
+        if (homePref.value !== homePref.defaultValue) {
+          homePref.value = homePref.defaultValue;
+        } else {
+          this._renderCustomSettings(false);
+        }
+        break;
+      case this.HOME_MODE_BLANK:
+        if (homePref.value !== "about:blank") {
+          homePref.value = "about:blank";
+        } else {
+          this._renderCustomSettings(false);
+        }
+        break;
+      case this.HOME_MODE_CUSTOM:
+        this._renderCustomSettings(true);
+        break;
+    }
+  },
+
+  /**
+   * Switches the "Use Current Page" button between its singular and plural
+   * forms.
+   */
+  async _updateUseCurrentButton() {
+    let useCurrent = document.getElementById("useCurrentBtn");
+    let tabs = this._getTabsForHomePage();
+    const tabCount = tabs.length;
+    document.l10n.setAttributes(useCurrent, "use-current-pages", { tabCount });
+
+    // If the homepage is controlled by an extension then you can't use this.
+    if (await getControllingExtensionInfo(PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY)) {
+      return;
+    }
+
+    // In this case, the button's disabled state is set by preferences.xml.
+    let prefName = "pref.browser.homepage.disable_button.current_page";
+    if (Preferences.get(prefName).locked)
+      return;
+
+    useCurrent.disabled = tabCount < 1;
+  },
+
+  /**
+   * Sets the home page to the URL(s) of any currently opened tab(s),
+   * updating about:preferences#home UI to reflect this.
+   */
+  setHomePageToCurrent() {
+    let homePage = Preferences.get("browser.startup.homepage");
+    let tabs = this._getTabsForHomePage();
+    function getTabURI(t) {
+      return t.linkedBrowser.currentURI.spec;
+    }
+
+    // FIXME Bug 244192: using dangerous "|" joiner!
+    if (tabs.length) {
+      homePage.value = tabs.map(getTabURI).join("|");
+    }
+
+    Services.telemetry.scalarAdd("preferences.use_current_page", 1);
+  },
+
+  _setHomePageToBookmarkClosed(rv, aEvent) {
+    if (aEvent.detail.button != "accept")
+      return;
+    if (rv.urls && rv.names) {
+      let homePage = Preferences.get("browser.startup.homepage");
+
+      // XXX still using dangerous "|" joiner!
+      homePage.value = rv.urls.join("|");
+    }
+  },
+
+   /**
+   * Displays a dialog in which the user can select a bookmark to use as home
+   * page.  If the user selects a bookmark, that bookmark's name is displayed in
+   * UI and the bookmark's address is stored to the home page preference.
+   */
+  setHomePageToBookmark() {
+    const rv = { urls: null, names: null };
+    gSubDialog.open("chrome://browser/content/preferences/selectBookmark.xul",
+      "resizable=yes, modal=yes", rv,
+      this._setHomePageToBookmarkClosed.bind(this, rv));
+    Services.telemetry.scalarAdd("preferences.use_bookmark", 1);
+  },
+
+  restoreDefaultHomePage() {
+    const homePref = Preferences.get("browser.startup.homepage");
+    const newtabPref = Preferences.get(this.NEWTAB_ENABLED_PREF);
+    homePref.value = homePref.defaultValue;
+    newtabPref.value = newtabPref.defaultValue;
+  },
+
+  onCustomHomePageInput(event) {
+    if (this._telemetryHomePageTimer) {
+      clearTimeout(this._telemetryHomePageTimer);
+    }
+    let browserHomePage = event.target.value;
+    // The length of the home page URL string should be more then four,
+    // and it should contain at least one ".", for example, "https://mozilla.org".
+    if (browserHomePage.length > 4 && browserHomePage.includes(".")) {
+      this._telemetryHomePageTimer = setTimeout(() => {
+        let homePageNumber = browserHomePage.split("|").length;
+        Services.telemetry.scalarAdd("preferences.browser_home_page_change", 1);
+        Services.telemetry.keyedScalarAdd("preferences.browser_home_page_count", homePageNumber, 1);
+      }, 3000);
+    }
+  },
+
+  onCustomHomePageChange(event) {
+    const homePref = Preferences.get("browser.startup.homepage");
+    const value = event.target.value || homePref.defaultValue;
+    homePref.value = value;
+  },
+
+  init() {
+    // Event Listeners
+    document.getElementById("homeMode").addEventListener("command", this.onMenuChange.bind(this));
+    document.getElementById("homePageUrl").addEventListener("change", this.onCustomHomePageChange.bind(this));
+    document.getElementById("homePageUrl").addEventListener("input", this.onCustomHomePageInput.bind(this));
+    document.getElementById("useCurrentBtn").addEventListener("command", this.setHomePageToCurrent.bind(this));
+    document.getElementById("useBookmarkBtn").addEventListener("command", this.setHomePageToBookmark.bind(this));
+    document.getElementById("restoreDefaultHomePageBtn").addEventListener("command", this.restoreDefaultHomePage.bind(this));
+
+    this._updateUseCurrentButton();
+    window.addEventListener("focus", this._updateUseCurrentButton.bind(this));
+
+    // Extension/override-related events
+    this.watchNewTab();
+    document.getElementById("disableHomePageExtension").addEventListener("command",
+      makeDisableControllingExtension(PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY));
+    document.getElementById("disableNewTabExtension").addEventListener("command",
+      makeDisableControllingExtension(URL_OVERRIDES_TYPE, NEW_TAB_KEY));
+  }
 };
--- a/browser/components/preferences/in-content/home.xul
+++ b/browser/components/preferences/in-content/home.xul
@@ -8,8 +8,96 @@
         src="chrome://browser/content/preferences/in-content/home.js"/>
 
 <hbox id="firefoxHomeCategory"
       class="subcategory"
       hidden="true"
       data-category="paneHome">
   <label class="header-name" flex="1" data-l10n-id="pane-home-title" />
 </hbox>
+
+<groupbox id="homepageGroup"
+          data-category="paneHome"
+          hidden="true">
+  <hbox>
+    <caption flex="1"><label data-l10n-id="home-new-windows-tabs-header" /></caption>
+    <button id="restoreDefaultHomePageBtn"
+            class="homepage-button check-home-page-controlled"
+            data-preference-related="browser.startup.homepage"
+            data-l10n-id="home-restore-defaults"
+            preference="pref.browser.homepage.disable_button.restore_default"/>
+  </hbox>
+  <description data-l10n-id="home-new-windows-tabs-description" />
+
+  <groupbox>
+    <hbox id="homepageAndNewWindowsOption">
+      <label control="homeMode" data-l10n-id="home-homepage-mode-label" flex="1" />
+
+      <vbox class="homepageMenuItemContainer" flex="1">
+        <textbox id="homePrefHidden"
+                preference="browser.startup.homepage"
+                onsyncfrompreference="return gHomePane.syncFromHomePref();"
+                hidden="true" />
+        <menulist id="homeMode"
+                  class="check-home-page-controlled"
+                  data-preference-related="browser.startup.homepage">
+          <menupopup>
+              <menuitem value="0" data-l10n-id="home-mode-choice-default" />
+              <menuitem value="2" data-l10n-id="home-mode-choice-custom" />
+              <menuitem value="1" data-l10n-id="home-mode-choice-blank" />
+          </menupopup>
+        </menulist>
+
+        <vbox id="customSettings" hidden="true">
+          <textbox id="homePageUrl"
+                  class="uri-element check-home-page-controlled"
+                  data-preference-related="browser.startup.homepage"
+                  type="autocomplete"
+                  data-l10n-id="home-homepage-custom-url"
+                  autocompletesearch="unifiedcomplete" />
+          <hbox class="homepage-buttons">
+            <button id="useCurrentBtn"
+                    flex="1"
+                    class="homepage-button check-home-page-controlled"
+                    data-l10n-id="use-current-pages"
+                    data-l10n-args='{"tabCount": 0}'
+                    disabled="true"
+                    preference="pref.browser.homepage.disable_button.current_page"/>
+            <button id="useBookmarkBtn"
+                    flex="1"
+                    class="homepage-button check-home-page-controlled"
+                    data-l10n-id="choose-bookmark"
+                    preference="pref.browser.homepage.disable_button.bookmark_page"
+                    searchkeywords="&selectBookmark.title; &selectBookmark.label;"/>
+          </hbox>
+        </vbox>
+      </vbox>
+    </hbox>
+    <hbox id="newTabsOption">
+      <label control="newTabMode" data-l10n-id="home-newtabs-mode-label" flex="1" />
+
+      <menulist id="newTabMode"
+                  flex="1"
+                  preference="browser.newtabpage.enabled"
+                  onsyncfrompreference="return gHomePane.syncFromNewTabPref();"
+                  onsynctopreference="return gHomePane.syncToNewTabPref(this.value);">
+        <menupopup>
+            <menuitem value="0" data-l10n-id="home-mode-choice-default" />
+            <menuitem value="1" data-l10n-id="home-mode-choice-blank" />
+        </menupopup>
+      </menulist>
+    </hbox>
+
+    <hbox id="browserHomePageExtensionContent" align="center" hidden="true">
+      <description control="disableHomePageExtension" flex="1" />
+      <button id="disableHomePageExtension"
+              class="extension-controlled-button accessory-button"
+              data-l10n-id="disable-extension" />
+    </hbox>
+    <hbox id="browserNewTabExtensionContent" align="center" hidden="true">
+      <description control="disableNewTabExtension" flex="1" />
+      <button id="disableNewTabExtension"
+              class="extension-controlled-button accessory-button"
+              data-l10n-id="disable-extension" />
+    </hbox>
+
+  </groupbox>
+</groupbox>
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -33,20 +33,16 @@ const PREF_CONTAINERS_EXTENSION = "priva
 
 // Preferences that affect which entries to show in the list.
 const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
 const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
   "browser.download.hide_plugins_without_extensions";
 
 // Strings to identify ExtensionSettingsStore overrides
 const CONTAINERS_KEY = "privacy.containers";
-const HOMEPAGE_OVERRIDE_KEY = "homepage_override";
-const URL_OVERRIDES_TYPE = "url_overrides";
-const NEW_TAB_KEY = "newTabURL";
-const NEW_TAB_STRING_ID = "extensionControlled.newTabURL2";
 
 /*
  * Preferences where we store handling information about the feed type.
  *
  * browser.feeds.handler
  * - "bookmarks", "reader" (clarified further using the .default preference),
  *   or "ask" -- indicates the default handler being used to process feeds;
  *   "bookmarks" is obsolete; to specify that the handler is bookmarks,
@@ -103,22 +99,16 @@ if (AppConstants.MOZ_DEV_EDITION) {
     "resource://gre/modules/FxAccounts.jsm");
   ChromeUtils.defineModuleGetter(this, "FxAccounts",
     "resource://gre/modules/FxAccounts.jsm");
 }
 
 Preferences.addAll([
   // Startup
   { id: "browser.startup.page", type: "int" },
-  { id: "browser.startup.homepage", type: "wstring" },
-
-  { id: "pref.browser.homepage.disable_button.current_page", type: "bool" },
-  { id: "pref.browser.homepage.disable_button.bookmark_page", type: "bool" },
-  { id: "pref.browser.homepage.disable_button.restore_default", type: "bool" },
-
   { id: "browser.privatebrowsing.autostart", type: "bool" },
 
   // Downloads
   { id: "browser.download.useDownloadDir", type: "bool" },
   { id: "browser.download.folderList", type: "int" },
   { id: "browser.download.dir", type: "file" },
 
   /* Tab preferences
@@ -349,35 +339,18 @@ var gMainPane = {
 
     let defaultPerformancePref =
       Preferences.get("browser.preferences.defaultPerformanceSettings.enabled");
     defaultPerformancePref.on("change", () => {
       this.updatePerformanceSettingsBox({ duringChangeEvent: true });
     });
     this.updatePerformanceSettingsBox({ duringChangeEvent: false });
 
-    // set up the "use current page" label-changing listener
-    this._updateUseCurrentButton();
-    window.addEventListener("focus", this._updateUseCurrentButton.bind(this));
-
     this.updateBrowserStartupLastSession();
 
-    handleControllingExtension(
-      URL_OVERRIDES_TYPE, NEW_TAB_KEY, NEW_TAB_STRING_ID);
-    let newTabObserver = {
-      observe(subject, topic, data) {
-        handleControllingExtension(
-          URL_OVERRIDES_TYPE, NEW_TAB_KEY, NEW_TAB_STRING_ID);
-      },
-    };
-    Services.obs.addObserver(newTabObserver, "newtab-url-changed");
-    window.addEventListener("unload", () => {
-      Services.obs.removeObserver(newTabObserver, "newtab-url-changed");
-    });
-
     let connectionSettingsLink = document.getElementById("connectionSettingsLearnMore");
     let connectionSettingsUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") +
                                 "prefs-connection-settings";
     connectionSettingsLink.setAttribute("href", connectionSettingsUrl);
     this.updateProxySettingsUI();
     initializeProxyUI(gMainPane);
 
     if (AppConstants.platform == "win") {
@@ -399,28 +372,18 @@ var gMainPane = {
       document.getElementById("warnOpenMany").hidden = true;
 
     Preferences.get("browser.privatebrowsing.autostart").on("change",
       gMainPane.updateBrowserStartupLastSession.bind(gMainPane));
     if (AppConstants.HAVE_SHELL_SERVICE) {
       setEventListener("setDefaultButton", "command",
         gMainPane.setDefaultBrowser);
     }
-    setEventListener("useCurrent", "command",
-      gMainPane.setHomePageToCurrent);
-    setEventListener("useBookmark", "command",
-      gMainPane.setHomePageToBookmark);
-    setEventListener("restoreDefaultHomePage", "command",
-      gMainPane.restoreDefaultHomePage);
-    setEventListener("disableHomePageExtension", "command",
-                     makeDisableControllingExtension(PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY));
     setEventListener("disableContainersExtension", "command",
                      makeDisableControllingExtension(PREF_SETTING_TYPE, CONTAINERS_KEY));
-    setEventListener("disableNewTabExtension", "command",
-                     makeDisableControllingExtension(URL_OVERRIDES_TYPE, NEW_TAB_KEY));
     setEventListener("chooseLanguage", "command",
       gMainPane.showLanguages);
     setEventListener("translationAttributionImage", "click",
       gMainPane.openTranslationProviderAttribution);
     setEventListener("translateButton", "command",
       gMainPane.showTranslationExceptions);
     Preferences.get("font.language.group").on("change",
       gMainPane._rebuildFonts.bind(gMainPane));
@@ -431,18 +394,16 @@ var gMainPane = {
     Preferences.get("layers.acceleration.disabled").on("change",
       gMainPane.updateHardwareAcceleration.bind(gMainPane));
     setEventListener("connectionSettings", "command",
       gMainPane.showConnections);
     setEventListener("browserContainersCheckbox", "command",
       gMainPane.checkBrowserContainers);
     setEventListener("browserContainersSettings", "command",
       gMainPane.showContainerSettings);
-    setEventListener("browserHomePage", "input",
-      gMainPane.onBrowserHomePageChange);
 
     // Initializes the fonts dropdowns displayed in this pane.
     this._rebuildFonts();
 
     this.updateOnScreenKeyboardVisibility();
 
     // Show translation preferences if we may:
     const prefName = "browser.translation.ui.show";
@@ -736,219 +697,32 @@ var gMainPane = {
       return;
     }
     let url = await FxAccounts.config.promiseSignInURI("dev-edition-setup");
     let accountsTab = win.gBrowser.addTab(url);
     win.gBrowser.selectedTab = accountsTab;
   },
 
   // HOME PAGE
-
   /*
    * Preferences:
    *
-   * browser.startup.homepage
-   * - the user's home page, as a string; if the home page is a set of tabs,
-   *   this will be those URLs separated by the pipe character "|"
    * browser.startup.page
    * - what page(s) to show when the user starts the application, as an integer:
    *
    *     0: a blank page
    *     1: the home page (as set by the browser.startup.homepage pref)
    *     2: the last page the user visited (DEPRECATED)
    *     3: windows and tabs from the last session (a.k.a. session restore)
    *
    *   The deprecated option is not exposed in UI; however, if the user has it
    *   selected and doesn't change the UI for this preference, the deprecated
    *   option is preserved.
    */
 
-  syncFromHomePref() {
-    let homePref = Preferences.get("browser.startup.homepage");
-
-    // Set the "Use Current Page(s)" button's text and enabled state.
-    this._updateUseCurrentButton();
-
-    function setInputDisabledStates(isControlled) {
-      let tabCount = this._getTabsForHomePage().length;
-
-      // Disable or enable the inputs based on if this is controlled by an extension.
-      document.querySelectorAll("#browserHomePage, .homepage-button")
-        .forEach((element) => {
-          let pref = element.getAttribute("preference");
-
-          let isDisabled = Preferences.get(pref).locked || isControlled;
-          if (pref == "pref.browser.disable_button.current_page") {
-            // Special case for current_page to disable it if tabCount is 0
-            isDisabled = isDisabled || tabCount < 1;
-          }
-
-          element.disabled = isDisabled;
-        });
-    }
-
-    if (homePref.locked) {
-      // An extension can't control these settings if they're locked.
-      hideControllingExtension(HOMEPAGE_OVERRIDE_KEY);
-      setInputDisabledStates.call(this, false);
-    } else {
-      // Asynchronously update the extension controlled UI.
-      handleControllingExtension(
-        PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY, "extensionControlled.homepage_override2")
-        .then(setInputDisabledStates.bind(this));
-    }
-
-    // If the pref is set to about:home or about:newtab, set the value to ""
-    // to show the placeholder text (about:home title) rather than
-    // exposing those URLs to users.
-    let defaultBranch = Services.prefs.getDefaultBranch("");
-    let defaultValue = defaultBranch.getComplexValue("browser.startup.homepage",
-      Ci.nsIPrefLocalizedString).data;
-    let currentValue = homePref.value.toLowerCase();
-    if (currentValue == "about:home" ||
-      (currentValue == defaultValue && currentValue == "about:newtab")) {
-      return "";
-    }
-
-    // If the pref is actually "", show about:blank.  The actual home page
-    // loading code treats them the same, and we don't want the placeholder text
-    // to be shown.
-    if (homePref.value == "")
-      return "about:blank";
-
-    // Otherwise, show the actual pref value.
-    return undefined;
-  },
-
-  syncToHomePref(value) {
-    // If the value is "", use about:home.
-    if (value == "")
-      return "about:home";
-
-    // Otherwise, use the actual textbox value.
-    return undefined;
-  },
-
-  /**
-   * Sets the home page to the current displayed page (or frontmost tab, if the
-   * most recent browser window contains multiple tabs), updating preference
-   * window UI to reflect this.
-   */
-  setHomePageToCurrent() {
-    let homePage = Preferences.get("browser.startup.homepage");
-    let tabs = this._getTabsForHomePage();
-    function getTabURI(t) {
-      return t.linkedBrowser.currentURI.spec;
-    }
-
-    // FIXME Bug 244192: using dangerous "|" joiner!
-    if (tabs.length) {
-      homePage.value = tabs.map(getTabURI).join("|");
-    }
-
-    Services.telemetry.scalarAdd("preferences.use_current_page", 1);
-  },
-
-  /**
-   * Displays a dialog in which the user can select a bookmark to use as home
-   * page.  If the user selects a bookmark, that bookmark's name is displayed in
-   * UI and the bookmark's address is stored to the home page preference.
-   */
-  setHomePageToBookmark() {
-    var rv = { urls: null, names: null };
-    gSubDialog.open("chrome://browser/content/preferences/selectBookmark.xul",
-      "resizable=yes, modal=yes", rv,
-      this._setHomePageToBookmarkClosed.bind(this, rv));
-    Services.telemetry.scalarAdd("preferences.use_bookmark", 1);
-  },
-
-  onBrowserHomePageChange() {
-    if (this.telemetryHomePageTimer) {
-      clearTimeout(this.telemetryHomePageTimer);
-    }
-    let browserHomePage = document.querySelector("#browserHomePage").value;
-    // The length of the home page URL string should be more then four,
-    // and it should contain at least one ".", for example, "https://mozilla.org".
-    if (browserHomePage.length > 4 && browserHomePage.includes(".")) {
-      this.telemetryHomePageTimer = setTimeout(() => {
-        let homePageNumber = browserHomePage.split("|").length;
-        Services.telemetry.scalarAdd("preferences.browser_home_page_change", 1);
-        Services.telemetry.keyedScalarAdd("preferences.browser_home_page_count", homePageNumber, 1);
-      }, 3000);
-    }
-  },
-
-  _setHomePageToBookmarkClosed(rv, aEvent) {
-    if (aEvent.detail.button != "accept")
-      return;
-    if (rv.urls && rv.names) {
-      var homePage = Preferences.get("browser.startup.homepage");
-
-      // XXX still using dangerous "|" joiner!
-      homePage.value = rv.urls.join("|");
-    }
-  },
-
-  /**
-   * Switches the "Use Current Page" button between its singular and plural
-   * forms.
-   */
-  async _updateUseCurrentButton() {
-    let useCurrent = document.getElementById("useCurrent");
-    let tabs = this._getTabsForHomePage();
-
-    const tabCount = tabs.length;
-
-    document.l10n.setAttributes(useCurrent, "use-current-pages", { tabCount });
-
-    // If the homepage is controlled by an extension then you can't use this.
-    if (await getControllingExtensionInfo(PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY)) {
-      return;
-    }
-
-    // In this case, the button's disabled state is set by preferences.xml.
-    let prefName = "pref.browser.homepage.disable_button.current_page";
-    if (Preferences.get(prefName).locked)
-      return;
-
-    useCurrent.disabled = tabCount < 1;
-  },
-
-  _getTabsForHomePage() {
-    var tabs = [];
-    var win = Services.wm.getMostRecentWindow("navigator:browser");
-
-    if (win && win.document.documentElement
-      .getAttribute("windowtype") == "navigator:browser") {
-      // We should only include visible & non-pinned tabs
-
-      tabs = win.gBrowser.visibleTabs.slice(win.gBrowser._numPinnedTabs);
-      tabs = tabs.filter(this.isNotAboutPreferences);
-      // XXX: Bug 1441637 - Fix tabbrowser to report tab.closing before it blurs it
-      tabs = tabs.filter(tab => !tab.closing);
-    }
-
-    return tabs;
-  },
-
-  /**
-   * Check to see if a tab is not about:preferences
-   */
-  isNotAboutPreferences(aElement, aIndex, aArray) {
-    return !aElement.linkedBrowser.currentURI.spec.startsWith("about:preferences");
-  },
-
-  /**
-   * Restores the default home page as the user's home page.
-   */
-  restoreDefaultHomePage() {
-    var homePage = Preferences.get("browser.startup.homepage");
-    homePage.value = homePage.defaultValue;
-  },
-
   /**
    * Utility function to enable/disable the button specified by aButtonID based
    * on the value of the Boolean preference specified by aPreferenceID.
    */
   updateButtons(aButtonID, aPreferenceID) {
     var button = document.getElementById(aButtonID);
     var preference = Preferences.get(aPreferenceID);
     button.disabled = !preference.value;
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -74,71 +74,20 @@
              id="browserStartupHomePage"/>
       <radio data-l10n-id="startup-blank-page"
              value="0"
              id="browserStartupBlank"/>
       <radio data-l10n-id="startup-prev-session"
              value="3"
              id="browserStartupLastSession"/>
     </radiogroup>
-    <hbox id="browserNewTabExtensionContent" align="center" hidden="true">
-      <description control="disableNewTabExtension" flex="1" />
-      <button id="disableNewTabExtension"
-              class="extension-controlled-button accessory-button"
-              data-l10n-id="disable-extension" />
-    </hbox>
+
   </vbox>
 </groupbox>
 
-<!-- Home Page -->
-<groupbox id="homepageGroup"
-          data-category="paneGeneral"
-          hidden="true">
-  <caption><label data-l10n-id="home-page-header"/></caption>
-
-  <hbox id="browserHomePageExtensionContent" align="center" hidden="true">
-    <description control="disableHomePageExtension" flex="1" />
-    <button id="disableHomePageExtension"
-            class="extension-controlled-button accessory-button"
-            data-l10n-id="disable-extension" />
-  </hbox>
-
-  <vbox>
-    <textbox id="browserHomePage"
-             class="uri-element"
-             type="autocomplete"
-             autocompletesearch="unifiedcomplete"
-             onsyncfrompreference="return gMainPane.syncFromHomePref();"
-             onsynctopreference="return gMainPane.syncToHomePref(this.value);"
-             placeholder="&abouthome.pageTitle;"
-             preference="browser.startup.homepage"/>
-  </vbox>
-
-  <hbox class="homepage-buttons">
-    <button id="useCurrent"
-            flex="1"
-            class="homepage-button"
-            data-l10n-id="use-current-pages"
-            data-l10n-args='{"tabCount": 0}'
-            disabled="true"
-            preference="pref.browser.homepage.disable_button.current_page"/>
-    <button id="useBookmark"
-            flex="1"
-            class="homepage-button"
-            data-l10n-id="choose-bookmark"
-            preference="pref.browser.homepage.disable_button.bookmark_page"
-            searchkeywords="&selectBookmark.title; &selectBookmark.label;"/>
-    <button id="restoreDefaultHomePage"
-            flex="1"
-            class="homepage-button"
-            data-l10n-id="restore-default"
-            preference="pref.browser.homepage.disable_button.restore_default"/>
-  </hbox>
-</groupbox>
-
 <!-- Tab preferences -->
 <groupbox data-category="paneGeneral"
           hidden="true">
     <caption><label data-l10n-id="tabs-group-header"/></caption>
 
     <checkbox id="ctrlTabRecentlyUsedOrder" data-l10n-id="ctrl-tab-recently-used-order"
               preference="browser.ctrlTab.previews"/>
 
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -140,17 +140,17 @@
 
         <richlistitem id="category-home"
                       class="category"
                       value="paneHome"
                       helpTopic="prefs-home"
                       data-l10n-id="category-home"
                       data-l10n-attrs="tooltiptext"
                       align="center"
-                      hidden="true">
+                      hidden="false">
           <image class="category-icon"/>
           <label class="category-name" flex="1" data-l10n-id="pane-home-title"></label>
         </richlistitem>
 
         <richlistitem id="category-search"
                       class="category"
                       value="paneSearch"
                       helpTopic="prefs-search"
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -77,42 +77,47 @@ function waitForEnableMessage(messageId,
 function waitForMessageContent(messageId, content, doc) {
   return waitForMessageChange(
     getElement(messageId, doc),
     target => target.textContent === content,
     { childList: true });
 }
 
 add_task(async function testExtensionControlledHomepage() {
-  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
   let doc = gBrowser.contentDocument;
-  is(gBrowser.currentURI.spec, "about:preferences#general",
-     "#general should be in the URI for about:preferences");
+  is(gBrowser.currentURI.spec, "about:preferences#home",
+     "#home should be in the URI for about:preferences");
   let homepagePref = () => Services.prefs.getCharPref("browser.startup.homepage");
   let originalHomepagePref = homepagePref();
   let extensionHomepage = "https://developer.mozilla.org/";
   let controlledContent = doc.getElementById("browserHomePageExtensionContent");
 
-  // The homepage is set to the default and editable.
+  let homeModeEl = doc.getElementById("homeMode");
+  let customSettingsSection = doc.getElementById("customSettings");
+
+  // The homepage is set to the default and the custom settings section is hidden
   ok(originalHomepagePref != extensionHomepage, "homepage is empty by default");
-  is(doc.getElementById("browserHomePage").disabled, false, "The homepage input is enabled");
+  is(homeModeEl.disabled, false, "The homepage menulist is enabled");
+  is(customSettingsSection.hidden, true, "The custom settings element is hidden");
   is(controlledContent.hidden, true, "The extension controlled row is hidden");
 
   // Install an extension that will set the homepage.
   await installAddon("set_homepage.xpi");
   await waitForMessageShown("browserHomePageExtensionContent");
 
   // The homepage has been set by the extension, the user is notified and it isn't editable.
   let controlledLabel = controlledContent.querySelector("description");
   is(homepagePref(), extensionHomepage, "homepage is set by extension");
   // There are two spaces before "set_homepage" because it's " <image /> set_homepage".
   is(controlledLabel.textContent, "An extension,  set_homepage, is controlling your home page.",
      "The user is notified that an extension is controlling the homepage");
   is(controlledContent.hidden, false, "The extension controlled row is hidden");
-  is(doc.getElementById("browserHomePage").disabled, true, "The homepage input is disabled");
+  is(homeModeEl.disabled, true, "The homepage input is disabled");
 
   // Disable the extension.
   let enableMessageShown = waitForEnableMessage(controlledContent.id);
   doc.getElementById("disableHomePageExtension").click();
   await enableMessageShown;
 
   // The user is notified how to enable the extension.
   is(controlledLabel.textContent, "To enable the extension go to  Add-ons in the  menu.",
@@ -120,53 +125,58 @@ add_task(async function testExtensionCon
 
   // The user can dismiss the enable instructions.
   let hidden = waitForMessageHidden("browserHomePageExtensionContent");
   controlledLabel.querySelector("image:last-of-type").click();
   await hidden;
 
   // The homepage elements are reset to their original state.
   is(homepagePref(), originalHomepagePref, "homepage is set back to default");
-  is(doc.getElementById("browserHomePage").disabled, false, "The homepage input is enabled");
+  is(homeModeEl.disabled, false, "The homepage menulist is enabled");
   is(controlledContent.hidden, true, "The extension controlled row is hidden");
 
   // Cleanup the add-on and tab.
   let addon = await AddonManager.getAddonByID("@set_homepage");
   // Enable the extension so we get the UNINSTALL event, which is needed by
   // ExtensionPreferencesManager to clean up properly.
   // FIXME: See https://bugzilla.mozilla.org/show_bug.cgi?id=1408226.
   addon.userDisabled = false;
   await waitForMessageShown("browserHomePageExtensionContent");
   // Do the uninstall now that the enable code has been run.
   addon.uninstall();
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function testPrefLockedHomepage() {
-  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
   let doc = gBrowser.contentDocument;
-  is(gBrowser.currentURI.spec, "about:preferences#general",
-     "#general should be in the URI for about:preferences");
+  is(gBrowser.currentURI.spec, "about:preferences#home",
+     "#home should be in the URI for about:preferences");
 
   let homePagePref = "browser.startup.homepage";
   let buttonPrefs = [
     "pref.browser.homepage.disable_button.current_page",
     "pref.browser.homepage.disable_button.bookmark_page",
     "pref.browser.homepage.disable_button.restore_default",
   ];
-  let homePageInput = doc.getElementById("browserHomePage");
+  let homeModeEl = doc.getElementById("homeMode");
+  let homePageInput = doc.getElementById("homePageUrl");
   let prefs = Services.prefs.getDefaultBranch(null);
   let mutationOpts = {attributes: true, attributeFilter: ["disabled"]};
   let controlledContent = doc.getElementById("browserHomePageExtensionContent");
 
   // Helper functions.
   let getButton = pref => doc.querySelector(`.homepage-button[preference="${pref}"`);
   let waitForAllMutations = () => Promise.all(
     buttonPrefs.map(pref => waitForMutation(getButton(pref), mutationOpts))
-    .concat([waitForMutation(homePageInput, mutationOpts)]));
+      .concat([
+        waitForMutation(homeModeEl, mutationOpts),
+        waitForMutation(homePageInput, mutationOpts)
+      ]));
   let getHomepage = () => Services.prefs.getCharPref("browser.startup.homepage");
 
   let originalHomepage = getHomepage();
   let extensionHomepage = "https://developer.mozilla.org/";
   let lockedHomepage = "http://www.yahoo.com";
 
   let lockPrefs = () => {
     buttonPrefs.forEach(pref => {
@@ -191,96 +201,105 @@ add_task(async function testPrefLockedHo
 
   // Install an extension that sets the homepage to MDN.
   await installAddon("set_homepage.xpi");
   await waitForMessageShown(controlledContent.id);
 
   // Check that everything is still disabled, homepage didn't change.
   is(getHomepage(), extensionHomepage, "The reported homepage is set by the extension");
   is(homePageInput.value, extensionHomepage, "The homepage is set by the extension");
-  is(homePageInput.disabled, true, "Homepage is disabled when set by extension");
+  is(homePageInput.disabled, true, "Homepage custom input is disabled when set by extension");
+  is(homeModeEl.disabled, true, "Homepage menulist is disabled when set by extension");
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, true, `${pref} is disabled when set by extension`);
   });
   is(controlledContent.hidden, false, "The extension controlled message is shown");
 
   // Lock all of the prefs, wait for the UI to update.
   let messageHidden = waitForMessageHidden(controlledContent.id);
+
   lockPrefs();
   await messageHidden;
 
   // Check that everything is now disabled.
   is(getHomepage(), lockedHomepage, "The reported homepage is set by the pref");
   is(homePageInput.value, lockedHomepage, "The homepage is set by the pref");
   is(homePageInput.disabled, true, "The homepage is disabed when the pref is locked");
+  is(homeModeEl.disabled, true, "Homepage menulist is disabled when the pref is locked");
+
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, true, `The ${pref} button is disabled when locked`);
   });
   is(controlledContent.hidden, true, "The extension controlled message is hidden when locked");
 
   // Unlock the prefs, wait for the UI to update.
   let messageShown = waitForMessageShown(controlledContent.id);
   unlockPrefs();
   await messageShown;
 
   // Verify that the UI is showing the extension's settings.
   is(homePageInput.value, extensionHomepage, "The homepage is set by the extension");
   is(homePageInput.disabled, true, "Homepage is disabled when set by extension");
+  is(homeModeEl.disabled, true, "Homepage menulist is disabled when set by extension");
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, true, `${pref} is disabled when set by extension`);
   });
   is(controlledContent.hidden, false, "The extension controlled message is shown when unlocked");
 
   // Uninstall the add-on.
   let addon = await AddonManager.getAddonByID("@set_homepage");
   addon.uninstall();
   await waitForEnableMessage(controlledContent.id);
 
   // Check that everything is now enabled again.
   is(getHomepage(), originalHomepage, "The reported homepage is reset to original value");
   is(homePageInput.value, "", "The homepage is empty");
   is(homePageInput.disabled, false, "The homepage is enabled after clearing lock");
+  is(homeModeEl.disabled, false, "Homepage menulist is enabled after clearing lock");
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, false, `The ${pref} button is enabled when unlocked`);
   });
 
   // Lock the prefs without an extension.
   lockPrefs();
   await waitForAllMutations();
 
   // Check that everything is now disabled.
   is(getHomepage(), lockedHomepage, "The reported homepage is set by the pref");
   is(homePageInput.value, lockedHomepage, "The homepage is set by the pref");
   is(homePageInput.disabled, true, "The homepage is disabed when the pref is locked");
+  is(homeModeEl.disabled, true, "Homepage menulist is disabled when prefis locked");
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, true, `The ${pref} button is disabled when locked`);
   });
 
   // Unlock the prefs without an extension.
   unlockPrefs();
   await waitForAllMutations();
 
   // Check that everything is enabled again.
   is(getHomepage(), originalHomepage, "The homepage is reset to the original value");
   is(homePageInput.value, "", "The homepage is clear after being unlocked");
   is(homePageInput.disabled, false, "The homepage is enabled after clearing lock");
+  is(homeModeEl.disabled, false, "Homepage menulist is enabled after clearing lock");
   buttonPrefs.forEach(pref => {
     is(getButton(pref).disabled, false, `The ${pref} button is enabled when unlocked`);
   });
   is(controlledContent.hidden, true,
      "The extension controlled message is hidden when unlocked with no extension");
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function testExtensionControlledNewTab() {
-  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
   let doc = gBrowser.contentDocument;
-  is(gBrowser.currentURI.spec, "about:preferences#general",
-     "#general should be in the URI for about:preferences");
+  is(gBrowser.currentURI.spec, "about:preferences#home",
+     "#home should be in the URI for about:preferences");
 
   let controlledContent = doc.getElementById("browserNewTabExtensionContent");
 
   // The new tab is set to the default and message is hidden.
   ok(!aboutNewTabService.newTabURL.startsWith("moz-extension:"), "new tab is not set");
   is(controlledContent.hidden, true, "The extension controlled row is hidden");
 
   // Install an extension that will set the new tab page.
@@ -411,26 +430,27 @@ add_task(async function testExtensionCon
 
   await originalExtension.unload();
   await updatedExtension.unload();
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function testExtensionControlledHomepageUninstalledAddon() {
   async function checkHomepageEnabled() {
-    await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+    await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+    // eslint-disable-next-line mozilla/no-cpows-in-tests
     let doc = gBrowser.contentDocument;
-    is(gBrowser.currentURI.spec, "about:preferences#general",
-      "#general should be in the URI for about:preferences");
+    is(gBrowser.currentURI.spec, "about:preferences#home",
+      "#home should be in the URI for about:preferences");
     let controlledContent = doc.getElementById("browserHomePageExtensionContent");
 
     // The homepage is enabled.
-    let homepageInut = doc.getElementById("browserHomePage");
-    is(homepageInut.disabled, false, "The homepage input is enabled");
-    is(homepageInut.value, "", "The homepage input is empty");
+    let homepageInput = doc.getElementById("homePageUrl");
+    is(homepageInput.disabled, false, "The homepage input is enabled");
+    is(homepageInput.value, "", "The homepage input is empty");
     is(controlledContent.hidden, true, "The extension controlled row is hidden");
 
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
 
   await ExtensionSettingsStore.initialize();
 
   // Verify the setting isn't reported as controlled and the inputs are enabled.
--- a/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
+++ b/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
@@ -1,18 +1,19 @@
 add_task(async function testSetHomepageUseCurrent() {
   is(gBrowser.currentURI.spec, "about:blank", "Test starts with about:blank open");
   await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home");
-  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
   let doc = gBrowser.contentDocument;
-  is(gBrowser.currentURI.spec, "about:preferences#general",
-     "#general should be in the URI for about:preferences");
+  is(gBrowser.currentURI.spec, "about:preferences#home",
+     "#home should be in the URI for about:preferences");
   let oldHomepagePref = Services.prefs.getCharPref("browser.startup.homepage");
 
-  let useCurrent = doc.getElementById("useCurrent");
+  let useCurrent = doc.getElementById("useCurrentBtn");
   useCurrent.click();
 
   is(gBrowser.tabs.length, 3, "Three tabs should be open");
   is(Services.prefs.getCharPref("browser.startup.homepage"), "about:blank|about:home",
      "about:blank and about:home should be the only homepages set");
 
   Services.prefs.setCharPref("browser.startup.homepage", oldHomepagePref);
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
--- a/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_1.js
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_1.js
@@ -6,17 +6,21 @@
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
 });
 
 /**
  * Test for searching for the "Set Home Page" subdialog.
  */
 add_task(async function() {
-  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await openPreferencesViaOpenPreferencesAPI("paneHome", {leaveOpen: true});
+
+  // Set custom URL so bookmark button will be shown on the page (otherwise it is hidden)
+  await SpecialPowers.pushPrefEnv({"set": [["browser.startup.homepage", "about:robots"]]});
+
   await evaluateSearchResults("Set Home Page", "homepageGroup");
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 /**
  * Test for searching for the "Languages" subdialog.
  */
 add_task(async function() {
--- a/browser/components/preferences/in-content/tests/browser_search_within_preferences_1.js
+++ b/browser/components/preferences/in-content/tests/browser_search_within_preferences_1.js
@@ -105,17 +105,16 @@ add_task(async function() {
   }
   await searchCompletedPromise;
 
   // Checks if back to generalPane
   for (let i = 0; i < mainPrefTag.childElementCount; i++) {
     let child = mainPrefTag.children[i];
     if (child.id == "paneGeneral"
       || child.id == "startupGroup"
-      || child.id == "homepageGroup"
       || child.id == "languagesGroup"
       || child.id == "fontsGroup"
       || child.id == "downloadsGroup"
       || child.id == "applicationsGroup"
       || child.id == "drmGroup"
       || child.id == "updateApp"
       || child.id == "browsingGroup"
       || child.id == "performanceGroup"
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -125,38 +125,16 @@ startup-user-homepage =
 startup-blank-page =
     .label = Show a blank page
 startup-prev-session =
     .label = Show your windows and tabs from last time
 
 disable-extension =
     .label = Disable Extension
 
-home-page-header = Home page
-
-# This string has a special case for '1' and [other] (default). If necessary for
-# your language, you can add {$tabCount} to your translations and use the
-# standard CLDR forms, or only use the form for [other] if both strings should
-# be identical.
-use-current-pages =
-    .label =
-        { $tabCount ->
-            [1] Use Current Page
-           *[other] Use Current Pages
-        }
-    .accesskey = C
-
-choose-bookmark =
-    .label = Use Bookmark…
-    .accesskey = B
-
-restore-default =
-    .label = Restore to Default
-    .accesskey = R
-
 tabs-group-header = Tabs
 
 ctrl-tab-recently-used-order =
     .label = Ctrl+Tab cycles through tabs in recently used order
     .accesskey = T
 
 open-new-link-as-tabs =
     .label = Open links in tabs instead of new windows
@@ -378,16 +356,62 @@ browsing-search-on-start-typing =
 network-proxy-title = Network Proxy
 
 network-proxy-connection-learn-more = Learn More
 
 network-proxy-connection-settings =
     .label = Settings…
     .accesskey = e
 
+## Home Section
+
+home-new-windows-tabs-header = New Windows and Tabs
+
+home-new-windows-tabs-description = Choose what you see when you open your homepage, new windows, and new tabs
+
+## Home Section - Home Page Customization
+
+home-homepage-mode-label = Homepage and new windows
+
+home-newtabs-mode-label = New tabs
+
+home-restore-defaults =
+    .label = Restore Defaults
+    .accesskey = R
+
+# "Firefox" should be treated as a brand and kept in English,
+# while "Home" and "(Default)" can be localized.
+home-mode-choice-default =
+    .label = Firefox Home (Default)
+
+home-mode-choice-custom =
+    .label = Custom URLs…
+
+home-mode-choice-blank =
+    .label = Blank Page
+
+home-homepage-custom-url =
+    .placeholder = Paste a URL…
+
+# This string has a special case for '1' and [other] (default). If necessary for
+# your language, you can add {$tabCount} to your translations and use the
+# standard CLDR forms, or only use the form for [other] if both strings should
+# be identical.
+use-current-pages =
+    .label =
+        { $tabCount ->
+            [1] Use Current Page
+           *[other] Use Current Pages
+        }
+    .accesskey = C
+
+choose-bookmark =
+    .label = Use Bookmark…
+    .accesskey = B
+
 ## Search Section
 
 search-bar-header = Search Bar
 search-bar-hidden =
     .label = Use the address bar for search and navigation
 search-bar-shown =
     .label = Add search bar in toolbar
 
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -183,30 +183,16 @@ button > hbox > label {
 #isDefaultLabel {
   font-weight: 600;
 }
 
 #startupPageBox {
   padding-top: 32px;
 }
 
-#browserHomePage {
-  margin-inline-start: 0;
-  margin-inline-end: 0;
-  margin-bottom: 4px;
-}
-
-.homepage-button:first-of-type {
-  margin-inline-start: 0;
-}
-
-.homepage-button:last-of-type {
-  margin-inline-end: 0;
-}
-
 .extension-controlled-icon {
   height: 20px;
   margin: 2px 0 6px;
   vertical-align: middle;
   width: 20px;
 }
 
 .extension-controlled-disabled {
@@ -230,21 +216,16 @@ button > hbox > label {
 #getStarted {
   font-size: 90%;
 }
 
 #downloadFolder {
   margin-inline-start: 0;
 }
 
-#browserHomePage:-moz-locale-dir(rtl) input {
-  unicode-bidi: plaintext;
-  direction: rtl;
-}
-
 #updateApp > .groupbox-body > label {
   margin: 0 0 4px;
 }
 
 #updateApp > .groupbox-body > description {
   margin: 0;
 }
 
@@ -310,16 +291,32 @@ button > hbox > label {
 .actionsMenu > menupopup > menuitem {
   padding-inline-start: 10px !important;
 }
 
 .actionsMenu > menupopup > menuitem > .menu-iconic-left {
   margin-inline-end: 8px !important;
 }
 
+/* Home Pane */
+#homepageGroup menulist,
+#homepageGroup textbox {
+  margin: 5px 0;
+}
+#homepageGroup:-moz-locale-dir(rtl) input {
+  unicode-bidi: plaintext;
+  direction: rtl;
+}
+.homepage-button:first-of-type {
+  margin-inline-start: 0;
+}
+.homepage-button:last-of-type {
+  margin-inline-end: 0;
+}
+
 /* Search Pane */
 
 #engineList {
   margin: 2px 0 5px;
 }
 
 #engineList > treechildren::-moz-tree-image(engineShown, checked),
 #blocklistsTree > treechildren::-moz-tree-image(selectionCol, checked) {