Backed out 5 changesets (bug 1501286) for browser-chrome failures in browser/components/uitour/test/browser_trackingProtection.js
authorDorel Luca <dluca@mozilla.com>
Thu, 25 Oct 2018 17:52:59 +0300
changeset 491342 5e471c480b8a6ba4939a6c159d86a687a24bb5d8
parent 491341 f01896424c3a2fa77c20f9b9b40da89a2a09c1ba
child 491343 8c16d6956679cac8745372056217ddb257f05171
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1501286
milestone65.0a1
backs outcac0d4aa79d1888f8b8886512be2b7d6b521c6d5
578d395f555ee3d71cacb239f5f84ce897b313cb
d9940451c3734f9de2f074005d81ef0e6ca4a3ec
ca6c3139bdd23efd00bc545df3bdf5a272650968
93d6f4d54f78c2e3898ac8395c1e4f3544537fbd
Backed out 5 changesets (bug 1501286) for browser-chrome failures in browser/components/uitour/test/browser_trackingProtection.js Backed out changeset cac0d4aa79d1 (bug 1501286) Backed out changeset 578d395f555e (bug 1501286) Backed out changeset d9940451c373 (bug 1501286) Backed out changeset ca6c3139bdd2 (bug 1501286) Backed out changeset 93d6f4d54f78 (bug 1501286)
browser/app/profile/firefox.js
browser/base/content/browser-contentblocking.js
browser/base/content/test/trackingUI/browser_trackingUI_appMenu_toggle.js
browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
browser/base/content/test/trackingUI/browser_trackingUI_state.js
browser/components/controlcenter/content/panel.inc.xul
browser/components/customizableui/content/panelUI.inc.xul
browser/components/preferences/in-content/extensionControlled.js
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/privacy.xul
browser/components/preferences/in-content/tests/browser_contentblocking.js
browser/components/preferences/in-content/tests/browser_extension_controlled.js
browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_6.js
browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_site_data.js
browser/components/preferences/in-content/tests/browser_spotlight.js
browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
browser/components/uitour/test/browser_contentBlocking.js
browser/components/uitour/test/browser_trackingProtection.js
browser/locales/en-US/browser/preferences/preferences.ftl
browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
browser/themes/shared/controlcenter/panel.inc.css
browser/themes/shared/incontentprefs/preferences.inc.css
browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css
browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.jsm
dom/indexedDB/test/test_third_party.html
dom/serviceworkers/test/test_third_party_iframes.html
dom/tests/mochitest/bugs/test_bug1171215.html
dom/tests/mochitest/general/storagePermissionsUtils.js
dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html
dom/workers/test/test_sharedWorker_thirdparty.html
extensions/cookie/test/file_testcommon.js
extensions/cookie/test/unit/test_cookies_thirdparty.js
modules/libpref/init/StaticPrefList.h
toolkit/components/antitracking/test/browser/browser_backgroundImageAssertion.js
toolkit/components/antitracking/test/browser/browser_existingCookiesForSubresources.js
toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
toolkit/components/antitracking/test/browser/browser_script.js
toolkit/components/antitracking/test/browser/browser_storageAccessWithHeuristics.js
toolkit/components/antitracking/test/browser/browser_subResources.js
toolkit/components/remotepagemanager/MessagePort.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1545,18 +1545,21 @@ pref("browser.contentblocking.reportBrea
 #else
 pref("browser.contentblocking.reportBreakage.enabled", false);
 #endif
 // Show report breakage for tracking cookies in all channels.
 pref("browser.contentblocking.rejecttrackers.reportBreakage.enabled", true);
 
 pref("browser.contentblocking.reportBreakage.url", "https://tracking-protection-issues.herokuapp.com/new");
 
+// Content Blocking has a separate pref for the intro count, since the former TP intro
+// was updated when we introduced content blocking and we want people to see it again.
 pref("browser.contentblocking.introCount", 0);
 
+pref("privacy.trackingprotection.introCount", 0);
 pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/");
 
 // Always enable newtab segregation using containers
 pref("privacy.usercontext.about_newtab_segregation.enabled", true);
 // Enable Contextual Identity Containers
 #ifdef NIGHTLY_BUILD
 pref("privacy.userContext.enabled", true);
 pref("privacy.userContext.ui.enabled", true);
--- a/browser/base/content/browser-contentblocking.js
+++ b/browser/base/content/browser-contentblocking.js
@@ -33,16 +33,42 @@ var TrackingProtection = {
   enabledInPrivateWindows: false,
 
   get categoryItem() {
     delete this.categoryItem;
     return this.categoryItem =
       document.getElementById("identity-popup-content-blocking-category-tracking-protection");
   },
 
+  strings: {
+    get enableTooltip() {
+      delete this.enableTooltip;
+      return this.enableTooltip =
+        gNavigatorBundle.getString("trackingProtection.toggle.enable.tooltip");
+    },
+
+    get disableTooltip() {
+      delete this.disableTooltip;
+      return this.disableTooltip =
+        gNavigatorBundle.getString("trackingProtection.toggle.disable.tooltip");
+    },
+
+    get disableTooltipPB() {
+      delete this.disableTooltipPB;
+      return this.disableTooltipPB =
+        gNavigatorBundle.getString("trackingProtection.toggle.disable.pbmode.tooltip");
+    },
+
+    get enableTooltipPB() {
+      delete this.enableTooltipPB;
+      return this.enableTooltipPB =
+        gNavigatorBundle.getString("trackingProtection.toggle.enable.pbmode.tooltip");
+    },
+  },
+
   init() {
     this.updateEnabled();
 
     Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
     Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
 
     XPCOMUtils.defineLazyPreferenceGetter(this, "visible", this.PREF_UI_ENABLED, false);
   },
@@ -57,21 +83,46 @@ var TrackingProtection = {
   },
 
   get enabled() {
     return this.enabledGlobally ||
            (this.enabledInPrivateWindows &&
             PrivateBrowsingUtils.isWindowPrivate(window));
   },
 
+  onGlobalToggleCommand() {
+    if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+      Services.prefs.setBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, !this.enabledInPrivateWindows);
+    } else {
+      Services.prefs.setBoolPref(this.PREF_ENABLED_GLOBALLY, !this.enabledGlobally);
+    }
+  },
+
   updateEnabled() {
     this.enabledGlobally =
       Services.prefs.getBoolPref(this.PREF_ENABLED_GLOBALLY);
     this.enabledInPrivateWindows =
       Services.prefs.getBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS);
+
+    if (!ContentBlocking.contentBlockingUIEnabled) {
+      ContentBlocking.updateEnabled();
+      let appMenuButton = ContentBlocking.appMenuButton;
+
+      if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+        appMenuButton.setAttribute("tooltiptext", this.enabledInPrivateWindows ?
+          this.strings.disableTooltipPB : this.strings.enableTooltipPB);
+        appMenuButton.setAttribute("enabled", this.enabledInPrivateWindows);
+        appMenuButton.setAttribute("aria-pressed", this.enabledInPrivateWindows);
+      } else {
+        appMenuButton.setAttribute("tooltiptext", this.enabledGlobally ?
+          this.strings.disableTooltip : this.strings.enableTooltip);
+        appMenuButton.setAttribute("enabled", this.enabledGlobally);
+        appMenuButton.setAttribute("aria-pressed", this.enabledGlobally);
+      }
+    }
   },
 
   isBlockerActivated(state) {
     return state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT;
   },
 };
 
 var ThirdPartyCookies = {
@@ -146,28 +197,30 @@ var ThirdPartyCookies = {
   },
 };
 
 
 var ContentBlocking = {
   // If the user ignores the doorhanger, we stop showing it after some time.
   MAX_INTROS: 20,
   PREF_ENABLED: "browser.contentblocking.enabled",
+  PREF_UI_ENABLED: "browser.contentblocking.ui.enabled",
   PREF_ANIMATIONS_ENABLED: "toolkit.cosmeticAnimations.enabled",
   PREF_REPORT_BREAKAGE_ENABLED: "browser.contentblocking.reportBreakage.enabled",
   PREF_REPORT_BREAKAGE_URL: "browser.contentblocking.reportBreakage.url",
   PREF_INTRO_COUNT_CB: "browser.contentblocking.introCount",
+  PREF_INTRO_COUNT_TP: "privacy.trackingprotection.introCount",
   PREF_GLOBAL_TOGGLE: "browser.contentblocking.global-toggle.enabled",
   content: null,
   icon: null,
   activeTooltipText: null,
   disabledTooltipText: null,
 
   get prefIntroCount() {
-    return this.PREF_INTRO_COUNT_CB;
+    return this.contentBlockingUIEnabled ? this.PREF_INTRO_COUNT_CB : this.PREF_INTRO_COUNT_TP;
   },
 
   get appMenuLabel() {
     delete this.appMenuLabel;
     return this.appMenuLabel = document.getElementById("appMenu-tp-label");
   },
 
   get appMenuButton() {
@@ -273,21 +326,21 @@ var ContentBlocking = {
     this.updateAnimationsEnabled();
 
     Services.prefs.addObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled);
 
     XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingEnabled", this.PREF_ENABLED, false,
       this.updateEnabled.bind(this));
     XPCOMUtils.defineLazyPreferenceGetter(this, "reportBreakageEnabled",
       this.PREF_REPORT_BREAKAGE_ENABLED, false);
+    XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingUIEnabled", this.PREF_UI_ENABLED, false,
+      this.updateUIEnabled.bind(this));
 
     this.updateEnabled();
-
-    this.appMenuLabel.setAttribute("label", this.strings.appMenuTitle);
-    this.appMenuLabel.setAttribute("tooltiptext", this.strings.appMenuTooltip);
+    this.updateUIEnabled();
 
     this.activeTooltipText =
       gNavigatorBundle.getString("trackingProtection.icon.activeTooltip");
     this.disabledTooltipText =
       gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip");
   },
 
   uninit() {
@@ -297,35 +350,52 @@ var ContentBlocking = {
       }
     }
 
     Services.prefs.removeObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled);
     Services.prefs.removeObserver(this.PREF_GLOBAL_TOGGLE, this.updateGlobalToggleVisibility);
   },
 
   get enabled() {
-    return this.contentBlockingEnabled;
+    return this.contentBlockingUIEnabled ? this.contentBlockingEnabled : TrackingProtection.enabled;
   },
 
   updateEnabled() {
     this.content.toggleAttribute("enabled", this.enabled);
 
-    this.appMenuButton.setAttribute("tooltiptext", this.enabled ?
-      this.strings.disableTooltip : this.strings.enableTooltip);
-    this.appMenuButton.setAttribute("enabled", this.enabled);
-    this.appMenuButton.setAttribute("aria-pressed", this.enabled);
+    if (this.contentBlockingUIEnabled) {
+      this.appMenuButton.setAttribute("tooltiptext", this.enabled ?
+        this.strings.disableTooltip : this.strings.enableTooltip);
+      this.appMenuButton.setAttribute("enabled", this.enabled);
+      this.appMenuButton.setAttribute("aria-pressed", this.enabled);
+    }
 
     // The enabled state of blockers may also change since it depends on this.enabled.
     for (let blocker of this.blockers) {
       blocker.categoryItem.classList.toggle("blocked", this.enabled && blocker.enabled);
     }
   },
 
+  updateUIEnabled() {
+    this.content.toggleAttribute("contentBlockingUI", this.contentBlockingUIEnabled);
+
+    if (this.contentBlockingUIEnabled) {
+      this.appMenuLabel.setAttribute("label", this.strings.appMenuTitle);
+      this.appMenuLabel.setAttribute("tooltiptext", this.strings.appMenuTooltip);
+    }
+
+    this.updateEnabled();
+  },
+
   onGlobalToggleCommand() {
-    Services.prefs.setBoolPref(this.PREF_ENABLED, !this.enabled);
+    if (this.contentBlockingUIEnabled) {
+      Services.prefs.setBoolPref(this.PREF_ENABLED, !this.enabled);
+    } else {
+      TrackingProtection.onGlobalToggleCommand();
+    }
   },
 
   hideIdentityPopupAndReload() {
     document.getElementById("identity-popup").hidePopup();
     BrowserReload();
   },
 
   openPreferences(origin) {
@@ -540,32 +610,40 @@ var ContentBlocking = {
       Services.prefs.savePrefFile(null);
     }
   },
 
   async showIntroPanel() {
     let brandBundle = document.getElementById("bundle_brand");
     let brandShortName = brandBundle.getString("brandShortName");
 
-
-    let introTitle = gNavigatorBundle.getFormattedString("contentBlocking.intro.title",
-                                                         [brandShortName]);
+    let introTitle;
     let introDescription;
     // This will be sent to the onboarding website to let them know which
     // UI variation we're showing.
     let variation;
-    // We show a different UI tour variation for users that already have TP
-    // enabled globally.
-    if (TrackingProtection.enabledGlobally) {
-      introDescription = gNavigatorBundle.getString("contentBlocking.intro.v2.description");
-      variation = 2;
+
+    if (this.contentBlockingUIEnabled) {
+      introTitle = gNavigatorBundle.getFormattedString("contentBlocking.intro.title",
+                                                       [brandShortName]);
+      // We show a different UI tour variation for users that already have TP
+      // enabled globally.
+      if (TrackingProtection.enabledGlobally) {
+        introDescription = gNavigatorBundle.getString("contentBlocking.intro.v2.description");
+        variation = 2;
+      } else {
+        introDescription = gNavigatorBundle.getFormattedString("contentBlocking.intro.v1.description",
+                                                               [brandShortName]);
+        variation = 1;
+      }
     } else {
-      introDescription = gNavigatorBundle.getFormattedString("contentBlocking.intro.v1.description",
+      introTitle = gNavigatorBundle.getString("trackingProtection.intro.title");
+      introDescription = gNavigatorBundle.getFormattedString("trackingProtection.intro.description2",
                                                              [brandShortName]);
-      variation = 1;
+      variation = 0;
     }
 
     let openStep2 = () => {
       // When the user proceeds in the tour, adjust the counter to indicate that
       // the user doesn't need to see the intro anymore.
       this.dontShowIntroPanelAgain();
 
       let nextURL = Services.urlFormatter.formatURLPref("privacy.trackingprotection.introURL") +
--- a/browser/base/content/test/trackingUI/browser_trackingUI_appMenu_toggle.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_appMenu_toggle.js
@@ -1,22 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const TOGGLE_PREF = "browser.contentblocking.global-toggle.enabled";
 
 ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
 
 // Test that the app menu toggle correctly flips the TP pref in
 // normal windows and private windows.
 add_task(async function testGlobalToggle() {
   await SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
     [TOGGLE_PREF, true],
   ]});
 
   let panelUIButton = await TestUtils.waitForCondition(() => document.getElementById("PanelUI-menu-button"));
 
   info("Opening main menu");
 
   let promiseShown = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown");
@@ -36,8 +38,56 @@ add_task(async function testGlobalToggle
   toggle.click();
   is(Services.prefs.getBoolPref(CB_PREF), false);
 
   toggle.click();
   is(Services.prefs.getBoolPref(CB_PREF), true);
 
   Services.prefs.clearUserPref(CB_PREF);
 });
+
+// Test that the app menu toggle correctly flips the TP pref in
+// normal windows and private windows.
+add_task(async function testGlobalToggleTP() {
+  await SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, false],
+    [TOGGLE_PREF, true],
+  ]});
+
+  async function runTest(privateWindow) {
+    let win = await BrowserTestUtils.openNewBrowserWindow({private: privateWindow});
+
+    let panelUIButton = await TestUtils.waitForCondition(() => win.document.getElementById("PanelUI-menu-button"));
+
+    let prefName = privateWindow ? "privacy.trackingprotection.pbmode.enabled" :
+      "privacy.trackingprotection.enabled";
+
+    info("Opening main menu");
+
+    let promiseShown = BrowserTestUtils.waitForEvent(win.PanelUI.mainView, "ViewShown");
+    panelUIButton.click();
+    await promiseShown;
+
+    info("Opened main menu");
+
+    let toggle = win.document.getElementById("appMenu-tp-toggle");
+
+    Services.prefs.setBoolPref(prefName, false);
+    await TestUtils.waitForCondition(() => toggle.getAttribute("enabled") == "false");
+
+    Services.prefs.setBoolPref(prefName, true);
+    await TestUtils.waitForCondition(() => toggle.getAttribute("enabled") == "true");
+
+    toggle.click();
+    is(Services.prefs.getBoolPref(prefName), false);
+
+    toggle.click();
+    is(Services.prefs.getBoolPref(prefName), true);
+
+    Services.prefs.clearUserPref(prefName);
+
+    await BrowserTestUtils.closeWindow(win);
+  }
+
+  // Run once in private and once in normal window.
+  await runTest(true);
+  await runTest(false);
+});
--- a/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
@@ -1,14 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const TP_PREF = "privacy.trackingprotection.enabled";
 const FB_PREF = "browser.fastblock.enabled";
 const TPC_PREF = "network.cookie.cookieBehavior";
 const FB_UI_PREF = "browser.contentblocking.fastblock.control-center.ui.enabled";
 const TP_UI_PREF = "browser.contentblocking.trackingprotection.control-center.ui.enabled";
 const RT_UI_PREF = "browser.contentblocking.rejecttrackers.control-center.ui.enabled";
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 
@@ -63,16 +64,17 @@ add_task(async function testOpenPreferen
   });
 });
 
 // Tests that clicking the contentblocking category items "add blocking" labels
 // links to about:preferences
 add_task(async function testOpenPreferencesFromAddBlockingButtons() {
   SpecialPowers.pushPrefEnv({set: [
     [CB_PREF, true],
+    [CB_UI_PREF, true],
     [FB_PREF, false],
     [TP_PREF, false],
     [TPC_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT],
     [FB_UI_PREF, true],
     [TP_UI_PREF, true],
     [RT_UI_PREF, true],
   ]});
 
--- a/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
@@ -1,15 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that sites added to the Tracking Protection whitelist in private
 // browsing mode don't persist once the private browsing window closes.
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const TP_PB_PREF = "privacy.trackingprotection.enabled";
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 var TrackingProtection = null;
 var ContentBlocking = null;
 var browser = null;
 
 registerCleanupFunction(function() {
   Services.prefs.clearUserPref(TP_PB_PREF);
@@ -55,21 +56,23 @@ function testTrackingPage(window) {
   } else {
     ok(!hidden("#tracking-action-unblock"), "unblockButton is visible");
     ok(hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is hidden");
   }
 
   ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
   ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
 
-  ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
-  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
-    "TP category item is not showing add blocking");
-  ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
-    "TP category item is set to blocked");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
+    ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
+      "TP category item is not showing add blocking");
+    ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
+      "TP category item is set to blocked");
+  }
 }
 
 function testTrackingPageUnblocked() {
   info("Tracking content must be white-listed and not blocked");
   ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
   ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
 
   ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
@@ -80,21 +83,23 @@ function testTrackingPageUnblocked() {
   ok(BrowserTestUtils.is_visible(ContentBlocking.iconBox), "icon box is visible");
   ok(!hidden("#tracking-action-block"), "blockButton is visible");
   ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
   ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
 
   ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
   ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
 
-  ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
-  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
-    "TP category item is not showing add blocking");
-  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
-    "TP category item is not set to blocked");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
+    ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
+      "TP category item is not showing add blocking");
+    ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
+      "TP category item is not set to blocked");
+  }
 }
 
 add_task(async function testExceptionAddition() {
   await UrlClassifierTestUtils.addTestTrackers();
   let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
   browser = privateWin.gBrowser;
   let tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser: browser, waitForLoad: true, waitForStateStop: true });
 
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -3,25 +3,29 @@
 
 "use strict";
 
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
 const COOKIE_PAGE = "http://not-tracking.example.com/browser/browser/base/content/test/trackingUI/cookiePage.html";
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const TP_PREF = "privacy.trackingprotection.enabled";
 const PREF_REPORT_BREAKAGE_ENABLED = "browser.contentblocking.reportBreakage.enabled";
 const PREF_REPORT_BREAKAGE_URL = "browser.contentblocking.reportBreakage.url";
 
 let {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js", {});
 let {CommonUtils} = ChromeUtils.import("resource://services-common/utils.js", {});
 let {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm", {});
 
 add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
+  ]});
   await UrlClassifierTestUtils.addTestTrackers();
 
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   registerCleanupFunction(() => {
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
--- a/browser/base/content/test/trackingUI/browser_trackingUI_state.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_state.js
@@ -10,16 +10,17 @@
  *   With TP disabled
  *     1) A page with no tracking elements is loaded.
  *     2) A page with tracking elements is loaded.
  *
  * See also Bugs 1175327, 1043801, 1178985
  */
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const TP_PREF = "privacy.trackingprotection.enabled";
 const TP_PB_PREF = "privacy.trackingprotection.pbmode.enabled";
 const FB_PREF = "browser.fastblock.enabled";
 const FB_TIMEOUT_PREF = "browser.fastblock.timeout";
 const FB_LIMIT_PREF = "browser.fastblock.limit";
 const TPC_PREF = "network.cookie.cookieBehavior";
 const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
@@ -74,17 +75,20 @@ function testBenignPage() {
   ok(BrowserTestUtils.is_hidden(ContentBlocking.iconBox), "icon box is hidden");
   ok(hidden("#tracking-action-block"), "blockButton is hidden");
   ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
   is(!hidden("#identity-popup-content-blocking-disabled-label"), !ContentBlocking.enabled,
     "disabled label is visible if CB is off");
 
   ok(!hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is visible");
   ok(hidden("#identity-popup-content-blocking-detected"), "blocking detected label is hidden");
-  ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
+
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
+  }
 }
 
 function testBenignPageWithException() {
   info("Non-tracking content must not be blocked");
   ok(!ContentBlocking.content.hasAttribute("detected"), "no trackers are detected");
   ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
   ok(!ContentBlocking.content.hasAttribute("active"), "content is not active");
 
@@ -98,17 +102,20 @@ function testBenignPageWithException() {
     "icon box is not hidden if CB is on");
   is(!hidden("#tracking-action-block"), ContentBlocking.enabled,
      "blockButton is visible if CB is on");
   ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
   ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
 
   ok(!hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is visible");
   ok(hidden("#identity-popup-content-blocking-detected"), "blocking detected label is hidden");
-  ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
+
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
+  }
 }
 
 function areTrackersBlocked(isPrivateBrowsing) {
   let cbEnabled = Services.prefs.getBoolPref(CB_PREF);
   let blockedByTP = cbEnabled &&
                     Services.prefs.getBoolPref(isPrivateBrowsing ? TP_PB_PREF : TP_PREF);
   let blockedByFB = cbEnabled &&
                     Services.prefs.getBoolPref(FB_PREF) &&
@@ -136,42 +143,45 @@ function testTrackingPage(window) {
   ok(!ContentBlocking.iconBox.hasAttribute("hasException"), "icon box shows no exception");
   is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
      blockedByTP ? gNavigatorBundle.getString("trackingProtection.icon.activeTooltip") : "",
      "correct tooltip");
 
   ok(hidden("#tracking-action-block"), "blockButton is hidden");
 
   let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
+  let cbUIEnabled = Services.prefs.getBoolPref(CB_UI_PREF);
   if (isWindowPrivate) {
     ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
     is(!hidden("#tracking-action-unblock-private"), blockedByTP,
        "unblockButtonPrivate is" + (blockedByTP ? "" : " not") + " visible");
   } else {
     ok(hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is hidden");
     is(!hidden("#tracking-action-unblock"), blockedByTP,
        "unblockButton is" + (blockedByTP ? "" : " not") + " visible");
   }
 
   ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
   ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
 
-  ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
-  let category;
-  if (Services.prefs.getBoolPref(FB_PREF)) {
-    category = "#identity-popup-content-blocking-category-fastblock";
-  } else {
-    category = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER ?
-                 "#identity-popup-content-blocking-category-3rdpartycookies" :
-                 "#identity-popup-content-blocking-category-tracking-protection";
+  if (cbUIEnabled) {
+    ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
+    let category;
+    if (Services.prefs.getBoolPref(FB_PREF)) {
+      category = "#identity-popup-content-blocking-category-fastblock";
+    } else {
+      category = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER ?
+                   "#identity-popup-content-blocking-category-3rdpartycookies" :
+                   "#identity-popup-content-blocking-category-tracking-protection";
+    }
+    is(hidden(category + " > .identity-popup-content-blocking-category-add-blocking"), blockedByTP,
+      "Category item is" + (blockedByTP ? " not" : "") + " showing add blocking");
+    is(hidden(category + " > .identity-popup-content-blocking-category-state-label"), !blockedByTP,
+      "Category item is" + (blockedByTP ? "" : " not") + " set to blocked");
   }
-  is(hidden(category + " > .identity-popup-content-blocking-category-add-blocking"), blockedByTP,
-    "Category item is" + (blockedByTP ? " not" : "") + " showing add blocking");
-  is(hidden(category + " > .identity-popup-content-blocking-category-state-label"), !blockedByTP,
-    "Category item is" + (blockedByTP ? "" : " not") + " set to blocked");
 
   if (Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER) {
     ok(hidden("#identity-popup-content-blocking-category-label-default"),
       "Not showing default cookie restrictions label.");
     ok(!hidden("#identity-popup-content-blocking-category-label-trackers"),
       "Showing trackers cookie restrictions label.");
   } else {
     ok(hidden("#identity-popup-content-blocking-category-label-trackers"),
@@ -181,17 +191,20 @@ function testTrackingPage(window) {
   }
 }
 
 function testTrackingPageUnblocked(blockedByTP, window) {
   info("Tracking content must be white-listed and not blocked");
   ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
   ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
 
-  let blockingEnabled = Services.prefs.getBoolPref(CB_PREF);
+  let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
+  let cbUIEnabled = Services.prefs.getBoolPref(CB_UI_PREF);
+  let tpEnabled = isWindowPrivate ? Services.prefs.getBoolPref(TP_PB_PREF) : Services.prefs.getBoolPref(TP_PREF);
+  let blockingEnabled = cbUIEnabled ? Services.prefs.getBoolPref(CB_PREF) : tpEnabled;
   ok(!ContentBlocking.content.hasAttribute("active"), "content is not active");
   ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
   is(ContentBlocking.iconBox.hasAttribute("hasException"), blockingEnabled,
      "shield" + (blockingEnabled ? " shows" : " doesn't show") + " exception");
   is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
      gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"), "correct tooltip");
 
   is(BrowserTestUtils.is_visible(ContentBlocking.iconBox), blockingEnabled,
@@ -199,30 +212,32 @@ function testTrackingPageUnblocked(block
   is(hidden("#tracking-action-block"), !blockingEnabled,
      "blockButton is" + (blockingEnabled ? " not" : "") + " visible");
   ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
   ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
 
   ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
   ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
 
-  ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
-  let category;
-  if (Services.prefs.getBoolPref(FB_PREF)) {
-    category = "#identity-popup-content-blocking-category-fastblock";
-  } else {
-    category = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER ?
-                 "#identity-popup-content-blocking-category-3rdpartycookies" :
-                 "#identity-popup-content-blocking-category-tracking-protection";
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
+    let category;
+    if (Services.prefs.getBoolPref(FB_PREF)) {
+      category = "#identity-popup-content-blocking-category-fastblock";
+    } else {
+      category = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER ?
+                   "#identity-popup-content-blocking-category-3rdpartycookies" :
+                   "#identity-popup-content-blocking-category-tracking-protection";
+    }
+    is(hidden(category + " > .identity-popup-content-blocking-category-add-blocking"), blockedByTP,
+      "Category item is" + (blockedByTP ? " not" : "") + " showing add blocking");
+    // Always hidden no matter if blockedByTP or not, since we have an exception.
+    ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
+      "TP category item is not set to blocked");
   }
-  is(hidden(category + " > .identity-popup-content-blocking-category-add-blocking"), blockedByTP,
-    "Category item is" + (blockedByTP ? " not" : "") + " showing add blocking");
-  // Always hidden no matter if blockedByTP or not, since we have an exception.
-  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
-    "TP category item is not set to blocked");
 }
 
 function testTrackingPageWithCBDisabled() {
   info("Tracking content must be white-listed and not blocked");
   ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
   ok(!ContentBlocking.content.hasAttribute("hasException"), "content shows no exception");
   ok(!ContentBlocking.content.hasAttribute("active"), "content is not active");
 
@@ -233,21 +248,23 @@ function testTrackingPageWithCBDisabled(
   ok(BrowserTestUtils.is_hidden(ContentBlocking.iconBox), "icon box is hidden");
   ok(hidden("#tracking-action-block"), "blockButton is hidden");
   ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
   ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
 
   ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
   ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
 
-  ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
-  ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
-    "TP category item is showing add blocking");
-  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
-    "TP category item is not set to blocked");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
+    ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
+      "TP category item is showing add blocking");
+    ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
+      "TP category item is not set to blocked");
+  }
 }
 
 async function testContentBlockingEnabled(tab) {
   info("Testing with Tracking Protection ENABLED.");
 
   info("Load a test page not containing tracking elements");
   await promiseTabLoadEvent(tab, BENIGN_PAGE);
   testBenignPage();
@@ -331,30 +348,40 @@ add_task(async function testNormalBrowsi
   is(TrackingProtection.enabled, Services.prefs.getBoolPref(TP_PREF),
      "TP.enabled is based on the original pref value");
 
   Services.prefs.setBoolPref(FB_PREF, false);
   Services.prefs.setIntPref(TPC_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
 
   await testContentBlockingEnabled(tab);
 
-  Services.prefs.setBoolPref(CB_PREF, false);
-  ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    Services.prefs.setBoolPref(CB_PREF, false);
+    ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  } else {
+    Services.prefs.setBoolPref(TP_PREF, false);
+    ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
+  }
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.setBoolPref(TP_PREF, true);
   ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
-  Services.prefs.setBoolPref(CB_PREF, false);
-  ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    Services.prefs.setBoolPref(CB_PREF, false);
+    ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  } else {
+    Services.prefs.setBoolPref(TP_PREF, false);
+    ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
+  }
 
   await testContentBlockingDisabled(tab);
 
   gBrowser.removeCurrentTab();
 
   Services.prefs.clearUserPref(FB_PREF);
   Services.prefs.clearUserPref(TPC_PREF);
 });
@@ -374,40 +401,55 @@ add_task(async function testPrivateBrows
   ok(ContentBlocking, "CB is attached to the private window");
   TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
   ok(TrackingProtection, "TP is attached to the private window");
   is(TrackingProtection.enabled, Services.prefs.getBoolPref(TP_PB_PREF),
      "TP.enabled is based on the pb pref value");
 
   await testContentBlockingEnabled(tab);
 
-  Services.prefs.setBoolPref(CB_PREF, false);
-  ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    Services.prefs.setBoolPref(CB_PREF, false);
+    ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  } else {
+    Services.prefs.setBoolPref(TP_PB_PREF, false);
+    ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
+  }
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.setBoolPref(TP_PB_PREF, true);
   ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(TrackingProtection.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
-  Services.prefs.setBoolPref(CB_PREF, false);
-  ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  if (Services.prefs.getBoolPref(CB_UI_PREF)) {
+    Services.prefs.setBoolPref(CB_PREF, false);
+    ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
+  } else {
+    Services.prefs.setBoolPref(TP_PB_PREF, false);
+    ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
+  }
 
   await testContentBlockingDisabled(tab);
 
   privateWin.close();
 
   Services.prefs.clearUserPref(FB_PREF);
   Services.prefs.clearUserPref(TPC_PREF);
 });
 
 add_task(async function testFastBlock() {
+  if (!SpecialPowers.getBoolPref(CB_UI_PREF)) {
+    info("The FastBlock test is disabled when the Content Blocking UI is disabled");
+    return;
+  }
+
   await UrlClassifierTestUtils.addTestTrackers();
 
   tabbrowser = gBrowser;
   let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser);
 
   Services.prefs.setBoolPref(FB_PREF, false);
   Services.prefs.setIntPref(TPC_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
 
@@ -417,43 +459,50 @@ add_task(async function testFastBlock() 
   ok(FastBlock, "TP is attached to the browser window");
   is(FastBlock.enabled, Services.prefs.getBoolPref(FB_PREF),
      "FB.enabled is based on the original pref value");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
+  ok(Services.prefs.getBoolPref(CB_UI_PREF), "CB UI must be enabled here");
   Services.prefs.setBoolPref(CB_PREF, false);
   ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.setBoolPref(FB_PREF, true);
   Services.prefs.setIntPref(FB_TIMEOUT_PREF, 0);
   Services.prefs.setIntPref(FB_LIMIT_PREF, 0);
   ok(FastBlock.enabled, "FB is enabled after setting the pref");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
+  ok(Services.prefs.getBoolPref(CB_UI_PREF), "CB UI must be enabled here");
   Services.prefs.setBoolPref(CB_PREF, false);
   ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.clearUserPref(FB_PREF);
   Services.prefs.clearUserPref(FB_TIMEOUT_PREF);
   Services.prefs.clearUserPref(FB_LIMIT_PREF);
   Services.prefs.clearUserPref(TPC_PREF);
   gBrowser.removeCurrentTab();
 });
 
 add_task(async function testThirdPartyCookies() {
+  if (!SpecialPowers.getBoolPref(CB_UI_PREF)) {
+    info("The ThirdPartyCookies test is disabled when the Content Blocking UI is disabled");
+    return;
+  }
+
   await UrlClassifierTestUtils.addTestTrackers();
   gTrackingPageURL = COOKIE_PAGE;
 
   Services.prefs.setBoolPref(FB_PREF, false);
 
   tabbrowser = gBrowser;
   let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser);
 
@@ -464,28 +513,30 @@ add_task(async function testThirdPartyCo
   is(ThirdPartyCookies.enabled,
      Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
      "TPC.enabled is based on the original pref value");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
+  ok(Services.prefs.getBoolPref(CB_UI_PREF), "CB UI must be enabled here");
   Services.prefs.setBoolPref(CB_PREF, false);
   ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.setIntPref(TPC_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER);
   ok(ThirdPartyCookies.enabled, "TPC is enabled after setting the pref");
   Services.prefs.setBoolPref(CB_PREF, true);
   ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
 
   await testContentBlockingEnabled(tab);
 
+  ok(Services.prefs.getBoolPref(CB_UI_PREF), "CB UI must be enabled here");
   Services.prefs.setBoolPref(CB_PREF, false);
   ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
 
   await testContentBlockingDisabled(tab);
 
   Services.prefs.clearUserPref(FB_PREF);
   Services.prefs.clearUserPref(TPC_PREF);
   gBrowser.removeCurrentTab();
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -54,30 +54,34 @@
       </hbox>
 
       <!-- Tracking Protection Section -->
       <hbox id="tracking-protection-container"
             class="identity-popup-section"
             when-connection="not-secure secure secure-ev secure-cert-user-overridden extension">
         <vbox id="identity-popup-content-blocking-content" flex="1">
           <hbox align="start">
+            <label id="tracking-protection-label"
+                   class="identity-popup-headline"
+                   flex="1">&trackingProtection.title;</label>
             <label id="content-blocking-label"
                    class="identity-popup-headline"
                    flex="1">&contentBlocking.title;</label>
             <hbox id="identity-popup-content-blocking-disabled-label">
               <image/>
               <label id="identity-popup-content-blocking-disabled-label-exception"
                      value="&contentBlocking.disabled.label;"
                      tooltiptext="&contentBlocking.exception.tooltip;"/>
               <label id="identity-popup-content-blocking-disabled-label-global"
                      value="&contentBlocking.disabled.label;"
                      tooltiptext="&contentBlocking.disabled.tooltip;"/>
             </hbox>
             <toolbarbutton id="tracking-protection-preferences-button"
                            class="identity-popup-preferences-button subviewbutton"
+                           tooltiptext="&trackingProtection.tooltip;"
                            oncommand="ContentBlocking.openPreferences('identityPopup-TP-preferencesButton'); gIdentityHandler.recordClick('cb_prefs_button');" />
           </hbox>
 
           <description id="identity-popup-content-blocking-detected"
                        crop="end">&contentBlocking.detected;</description>
           <description id="identity-popup-content-blocking-not-detected"
                        crop="end">&contentBlocking.notDetected;</description>
 
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -221,18 +221,20 @@
                          class="subviewbutton subviewbutton-iconic"
                          onmouseover="gSync.refreshSyncButtonsTooltip();"
                          oncommand="gSync.doSync();"
                          closemenu="none"/>
         </toolbaritem>
         <toolbarseparator class="sync-ui-item"/>
         <toolbaritem closemenu="none">
           <toolbarbutton id="appMenu-tp-label"
+                         tooltiptext="&trackingProtection.tooltip;"
                          class="subviewbutton subviewbutton-iconic"
-                         oncommand="ContentBlocking.openPreferences('appMenu-trackingprotection'); PanelUI.hide();"/>
+                         oncommand="ContentBlocking.openPreferences('appMenu-trackingprotection'); PanelUI.hide();"
+                         label="&trackingProtection.title;"/>
           <toolbarseparator id="appMenu-tp-vertical-separator" orient="vertical"/>
           <toolbarbutton id="appMenu-tp-toggle"
                          enabled="false"
                          oncommand="ContentBlocking.onGlobalToggleCommand();" />
         </toolbaritem>
         <toolbarseparator id="appMenu-tp-separator"/>
         <toolbarbutton id="appMenu-new-window-button"
                        class="subviewbutton subviewbutton-iconic"
--- a/browser/components/preferences/in-content/extensionControlled.js
+++ b/browser/components/preferences/in-content/extensionControlled.js
@@ -12,16 +12,19 @@ ChromeUtils.defineModuleGetter(this, "Ad
                                   "resource://gre/modules/AddonManager.jsm");
 ChromeUtils.defineModuleGetter(this, "BrowserUtils",
                                   "resource://gre/modules/BrowserUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "DeferredTask",
                                   "resource://gre/modules/DeferredTask.jsm");
 ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
                                   "resource://gre/modules/ExtensionSettingsStore.jsm");
 
+XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingUiEnabled",
+                                      "browser.contentblocking.ui.enabled");
+
 const PREF_SETTING_TYPE = "prefs";
 const PROXY_KEY = "proxy.settings";
 const API_PROXY_PREFS = [
   "network.proxy.type",
   "network.proxy.http",
   "network.proxy.http_port",
   "network.proxy.share_proxy_settings",
   "network.proxy.ftp",
@@ -41,29 +44,35 @@ let extensionControlledContentIds = {
   "privacy.containers": "browserContainersExtensionContent",
   "homepage_override": "browserHomePageExtensionContent",
   "newTabURL": "browserNewTabExtensionContent",
   "webNotificationsDisabled": "browserNotificationsPermissionExtensionContent",
   "defaultSearch": "browserDefaultSearchExtensionContent",
   "proxy.settings": "proxyExtensionContent",
   get "websites.trackingProtectionMode"() {
     return {
-      button: "contentBlockingDisableTrackingProtectionExtension",
-      section: "contentBlockingTrackingProtectionExtensionContentLabel",
+      button: contentBlockingUiEnabled ?
+        "contentBlockingDisableTrackingProtectionExtension" :
+        "trackingProtectionExtensionContentButton",
+      section: contentBlockingUiEnabled ?
+        "contentBlockingTrackingProtectionExtensionContentLabel" :
+        "trackingProtectionExtensionContentLabel",
     };
   },
 };
 
 const extensionControlledL10nKeys = {
   "homepage_override": "homepage-override",
   "newTabURL": "new-tab-url",
   "webNotificationsDisabled": "web-notifications",
   "defaultSearch": "default-search",
   "privacy.containers": "privacy-containers",
-  "websites.trackingProtectionMode": "websites-content-blocking-all-trackers",
+  "websites.trackingProtectionMode": contentBlockingUiEnabled ?
+                                       "websites-content-blocking-all-trackers" :
+                                       "websites-tracking-protection-mode",
   "proxy.settings": "proxy-config",
 };
 
 let extensionControlledIds = {};
 
 /**
   * Check if a pref is being managed by an extension.
   */
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -15,16 +15,19 @@ ChromeUtils.defineModuleGetter(this, "Pl
   "resource://gre/modules/PluralForm.jsm");
 ChromeUtils.defineModuleGetter(this, "LoginHelper",
   "resource://gre/modules/LoginHelper.jsm");
 ChromeUtils.defineModuleGetter(this, "SiteDataManager",
   "resource:///modules/SiteDataManager.jsm");
 
 ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
+XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingUiEnabled",
+                                      "browser.contentblocking.ui.enabled");
+
 XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingCookiesAndSiteDataRejectTrackersRecommended",
                                       "browser.contentblocking.cookies-site-data.ui.reject-trackers.recommended");
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingCookiesAndSiteDataRejectTrackersEnabled",
                                       "browser.contentblocking.cookies-site-data.ui.reject-trackers.enabled");
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingFastBlockUiEnabled",
                                       "browser.contentblocking.fastblock.ui.enabled");
@@ -177,33 +180,55 @@ var gPrivacyPane = {
   _pane: null,
 
   /**
    * Whether the prompt to restart Firefox should appear when changing the autostart pref.
    */
   _shouldPromptForRestart: true,
 
   /**
+   * Initialize the tracking protection prefs and linkify its Learn More link.
+   */
+  _initTrackingProtection() {
+    setEventListener("trackingProtectionRadioGroup", "command",
+      this.trackingProtectionWritePrefs);
+    setEventListener("changeBlockList", "command", this.showBlockLists);
+
+    let link = document.getElementById("trackingProtectionLearnMore");
+    let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection";
+    link.setAttribute("href", url);
+  },
+
+  /**
    * Update the tracking protection UI to deal with extension control.
    */
   _updateTrackingProtectionUI() {
     let isLocked = TRACKING_PROTECTION_PREFS.some(
       pref => Services.prefs.prefIsLocked(pref));
 
     function setInputsDisabledState(isControlled) {
       let disabled = isLocked || isControlled;
-      let tpCheckbox =
-        document.getElementById("contentBlockingTrackingProtectionCheckbox");
-      // Only enable the TP menu if content blocking and Detect All Trackers
-      // are enabled.
-      document.getElementById("trackingProtectionMenu").disabled = disabled ||
-        !tpCheckbox.checked ||
-        !contentBlockingEnabled;
-      // Only enable the TP category checkbox if content blocking is enabled.
-      tpCheckbox.disabled = disabled || !contentBlockingEnabled;
+      if (contentBlockingUiEnabled) {
+        let tpCheckbox =
+          document.getElementById("contentBlockingTrackingProtectionCheckbox");
+        // Only enable the TP menu if content blocking and Detect All Trackers
+        // are enabled.
+        document.getElementById("trackingProtectionMenu").disabled = disabled ||
+          !tpCheckbox.checked ||
+          !contentBlockingEnabled;
+        // Only enable the TP category checkbox if content blocking is enabled.
+        tpCheckbox.disabled = disabled || !contentBlockingEnabled;
+      } else {
+        document.querySelectorAll("#trackingProtectionRadioGroup > radio")
+          .forEach((element) => {
+            element.disabled = disabled;
+          });
+        document.querySelector("#trackingProtectionDesc > label")
+          .disabled = disabled;
+      }
 
       // Notify observers that the TP UI has been updated.
       // This is needed since our tests need to be notified about the
       // trackingProtectionMenu element getting disabled/enabled at the right time.
       Services.obs.notifyObservers(window, "privacy-pane-tp-ui-updated");
     }
 
     if (isLocked) {
@@ -218,17 +243,19 @@ var gPrivacyPane = {
     }
   },
 
   /**
    * Set up handlers for showing and hiding controlling extension info
    * for tracking protection.
    */
   _initTrackingProtectionExtensionControl() {
-    setEventListener("contentBlockingDisableTrackingProtectionExtension", "command",
+    let disableButton = contentBlockingUiEnabled ?
+      "contentBlockingDisableTrackingProtectionExtension" : "disableTrackingProtectionExtension";
+    setEventListener(disableButton, "command",
       makeDisableControllingExtension(
         PREF_SETTING_TYPE, TRACKING_PROTECTION_KEY));
 
     let trackingProtectionObserver = {
       observe(subject, topic, data) {
         gPrivacyPane._updateTrackingProtectionUI();
       },
     };
@@ -260,18 +287,23 @@ var gPrivacyPane = {
     this.initializeHistoryMode();
     this.initAutoplay();
     this.updateAutoplayMediaControlsVisibility();
     this.updateHistoryModePane();
     this.updatePrivacyMicroControls();
     this.initAutoStartPrivateBrowsingReverter();
     this._initAutocomplete();
 
-    /* Initialize Content Blocking */
-    this.initContentBlocking();
+    /* Initialize Content Blocking / Tracking Protection */
+
+    if (contentBlockingUiEnabled) {
+      this.initContentBlocking();
+    } else {
+      this._initTrackingProtection();
+    }
 
     this.trackingProtectionReadPrefs();
     this.networkCookieBehaviorReadPrefs();
     this._initTrackingProtectionExtensionControl();
 
     this.updateContentBlockingVisibility();
 
     Preferences.get("privacy.trackingprotection.enabled").on("change",
@@ -530,23 +562,48 @@ var gPrivacyPane = {
   /**
    * Highlights the Cookies & Site Data UI section.
    */
   changeCookieSettings() {
     gotoPref("privacy-sitedata");
   },
 
   /**
-   * Changes the visibility of elements in the CB section depending on the
-   * content blocking UI prefs.
+   * Changes the visibility of elements in the TP/CB section depending on the
+   * content blocking UI pref.
    */
   updateContentBlockingVisibility() {
-    // Potentially hide the global toggle.
-    document.getElementById("contentBlockingCheckboxContainer").hidden =
-      !Services.prefs.getBoolPref("browser.contentblocking.global-toggle.enabled", true);
+    // First, update the content blocking UI.
+    let visibleState = {
+      "contentBlockingHeader": true,
+      "contentBlockingDescription": true,
+      "contentBlockingLearnMore": true,
+      "contentBlockingRestoreDefaults": true,
+      "contentBlockingCheckboxContainer": true,
+      "contentBlockingCategories": true,
+
+      "trackingProtectionHeader": false,
+      "trackingProtectionDescription": false,
+      "trackingProtectionBox": false,
+    };
+    for (let id in visibleState) {
+      document.getElementById(id).hidden = contentBlockingUiEnabled != visibleState[id];
+    }
+
+    if (contentBlockingUiEnabled) {
+      // Update the Do Not Track section to not mention "Tracking Protection".
+      let dntDefaultRadioItem =
+        document.querySelector("#doNotTrackRadioGroup > radio[value=false]");
+      document.l10n.setAttributes(
+        dntDefaultRadioItem, "do-not-track-option-default-content-blocking");
+
+      // Potentially hide the global toggle.
+      document.getElementById("contentBlockingCheckboxContainer").hidden =
+        !Services.prefs.getBoolPref("browser.contentblocking.global-toggle.enabled", true);
+    }
 
     // Allow turning off the "(recommended)" label using a pref
     let blockCookiesFromTrackers = document.getElementById("blockCookiesFromTrackers");
     if (contentBlockingCookiesAndSiteDataRejectTrackersRecommended) {
       document.l10n.setAttributes(blockCookiesFromTrackers, "sitedata-block-trackers-option-recommended");
     }
 
     // Allow hiding the Reject Trackers option based on a pref
@@ -626,25 +683,33 @@ var gPrivacyPane = {
 
   /**
    * Selects the right item of the Tracking Protection radiogroup.
    */
   trackingProtectionReadPrefs() {
     let enabledPref = Preferences.get("privacy.trackingprotection.enabled");
     let pbmPref = Preferences.get("privacy.trackingprotection.pbmode.enabled");
     let btpmPref = Preferences.get("browser.privacy.trackingprotection.menu");
-    let tpControl = document.getElementById("trackingProtectionMenu");
-    let tpCheckbox = document.getElementById("contentBlockingTrackingProtectionCheckbox");
+    let tpControl,
+        tpCheckbox;
+    if (contentBlockingUiEnabled) {
+      tpControl = document.getElementById("trackingProtectionMenu");
+      tpCheckbox = document.getElementById("contentBlockingTrackingProtectionCheckbox");
+    } else {
+      tpControl = document.getElementById("trackingProtectionRadioGroup");
+    }
 
     let savedMenuValue;
-    // Only look at the backup pref when restoring the checkbox next to
-    // "All Detected Trackers".
-    if (["always", "private"].includes(btpmPref.value) &&
-        tpCheckbox.checked) {
-      savedMenuValue = btpmPref.value;
+    if (contentBlockingUiEnabled) {
+      // Only look at the backup pref when restoring the checkbox next to
+      // "All Detected Trackers".
+      if (["always", "private"].includes(btpmPref.value) &&
+          tpCheckbox.checked) {
+        savedMenuValue = btpmPref.value;
+      }
     }
 
     this._updateTrackingProtectionUI();
 
     // Global enable takes precedence over enabled in Private Browsing.
     if (enabledPref.value) {
       tpControl.value = "always";
       if (tpCheckbox) {
@@ -671,17 +736,17 @@ var gPrivacyPane = {
   networkCookieBehaviorReadPrefs() {
     let behavior = Preferences.get("network.cookie.cookieBehavior").value;
     let blockCookiesCtrl = document.getElementById("blockCookies");
     let blockCookiesLabel = document.getElementById("blockCookiesLabel");
     let blockCookiesMenu = document.getElementById("blockCookiesMenu");
     let keepUntilLabel = document.getElementById("keepUntil");
     let keepUntilMenu = document.getElementById("keepCookiesUntil");
 
-    let disabledByCB = !contentBlockingEnabled;
+    let disabledByCB = contentBlockingUiEnabled ? !contentBlockingEnabled : false;
     let blockCookies = (behavior != 0);
     let cookieBehaviorLocked = Services.prefs.prefIsLocked("network.cookie.cookieBehavior");
     let blockCookiesControlsDisabled = !blockCookies || cookieBehaviorLocked || disabledByCB;
     blockCookiesLabel.disabled = blockCookiesMenu.disabled = blockCookiesControlsDisabled;
 
     let completelyBlockCookies = (behavior == 2);
     let privateBrowsing = Preferences.get("browser.privatebrowsing.autostart").value;
     let cookieExpirationLocked = Services.prefs.prefIsLocked("network.cookie.lifetimePolicy");
@@ -714,18 +779,24 @@ var gPrivacyPane = {
 
   /**
    * Sets the pref values based on the selected item of the radiogroup.
    */
   trackingProtectionWritePrefs() {
     let enabledPref = Preferences.get("privacy.trackingprotection.enabled");
     let pbmPref = Preferences.get("privacy.trackingprotection.pbmode.enabled");
     let btpmPref = Preferences.get("browser.privacy.trackingprotection.menu");
-    let tpControl = document.getElementById("trackingProtectionMenu");
-    let tpCheckbox = document.getElementById("contentBlockingTrackingProtectionCheckbox");
+    let tpControl,
+        tpCheckbox;
+    if (contentBlockingUiEnabled) {
+      tpControl = document.getElementById("trackingProtectionMenu");
+      tpCheckbox = document.getElementById("contentBlockingTrackingProtectionCheckbox");
+    } else {
+      tpControl = document.getElementById("trackingProtectionRadioGroup");
+    }
 
     let value;
     if (tpCheckbox) {
       if (tpCheckbox.checked) {
         value = tpControl.value;
         btpmPref.value = value;
       } else {
         value = "never";
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -14,21 +14,25 @@
       hidden="true"
       data-category="panePrivacy">
   <label class="header-name" flex="1" data-l10n-id="privacy-header"/>
 </hbox>
 
 <!-- Tracking / Content Blocking -->
 <groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" aria-describedby="contentBlockingDescription">
   <caption>
+    <label id="trackingProtectionHeader" hidden="true" data-l10n-id="tracking-header"/>
     <label id="contentBlockingHeader" data-l10n-id="content-blocking-header"/>
   </caption>
   <vbox data-subcategory="trackingprotection">
     <hbox align="start">
       <vbox flex="1">
+        <description id="trackingProtectionDescription" class="description-with-side-element" hidden="true" data-l10n-id="tracking-desc">
+          <html:a id="trackingProtectionLearnMore" data-l10n-name="learn-more" target="_blank" class="learnMore text-link"/>
+        </description>
         <description id="contentBlockingDescription" class="description-with-side-element" data-l10n-id="content-blocking-desc"></description>
         <label id="contentBlockingLearnMore" data-l10n-id="content-blocking-learn-more" class="learnMore text-link"/>
       </vbox>
       <vbox>
         <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
         <hbox>
           <button id="contentBlockingRestoreDefaults"
                   class="accessory-button"
@@ -156,23 +160,63 @@
                        data-l10n-id="content-blocking-reject-trackers-all-third-parties-option"
                        flex="1" />
               </radiogroup>
             </vbox>
           </vbox>
         </hbox>
       </hbox>
     </vbox>
+    <hbox id="trackingProtectionBox" hidden="true">
+      <vbox flex="1">
+        <vbox>
+          <hbox id="trackingProtectionExtensionContentLabel" align="center" hidden="true">
+            <description control="disableTrackingProtectionExtension" flex="1"/>
+          </hbox>
+          <vbox>
+            <description id="trackingProtectionDesc"
+                         control="trackingProtectionRadioGroup">
+              <label data-l10n-id="tracking-mode-label"/>
+            </description>
+            <radiogroup id="trackingProtectionRadioGroup" aria-labelledby="trackingProtectionDesc">
+              <radio value="always"
+                     data-l10n-id="tracking-mode-always"/>
+              <radio value="private"
+                     data-l10n-id="tracking-mode-private"/>
+              <radio value="never"
+                     data-l10n-id="tracking-mode-never"/>
+            </radiogroup>
+          </vbox>
+        </vbox>
+      </vbox>
+      <vbox id="trackingProtectionAdvancedSettings">
+        <hbox id="trackingProtectionExtensionContentButton" hidden="true">
+          <button id="disableTrackingProtectionExtension"
+                  class="extension-controlled-button accessory-button"
+                  flex="1"
+                  data-l10n-id="disable-extension"/>
+        </hbox>
+        <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
+        <hbox>
+          <button id="changeBlockList"
+                  class="accessory-button"
+                  flex="1"
+                  data-l10n-id="tracking-change-block-list"
+                  preference="pref.privacy.disable_button.change_blocklist"
+                  search-l10n-ids="blocklist-window.title, blocklist-desc, blocklist-button-cancel.label, blocklist-button-ok.label"/>
+        </hbox>
+      </vbox>
+    </hbox>
     <vbox id="doNotTrackLearnMoreBox">
       <label><label class="tail-with-learn-more" data-l10n-id="do-not-track-description" id="doNotTrackDesc"></label><label
       class="learnMore text-link" href="https://www.mozilla.org/dnt"
       data-l10n-id="do-not-track-learn-more"></label></label>
       <radiogroup id="doNotTrackRadioGroup" aria-labelledby="doNotTrackDesc" preference="privacy.donottrackheader.enabled">
         <radio value="true" data-l10n-id="do-not-track-option-always"/>
-        <radio value="false" data-l10n-id="do-not-track-option-default-content-blocking"/>
+        <radio value="false" data-l10n-id="do-not-track-option-default"/>
       </radiogroup>
     </vbox>
   </vbox>
 </groupbox>
 
 <!-- Site Data -->
 <groupbox id="siteDataGroup" data-category="panePrivacy" hidden="true" aria-describedby="totalSiteDataSize">
   <caption><label data-l10n-id="sitedata-header"/></caption>
--- a/browser/components/preferences/in-content/tests/browser_contentblocking.js
+++ b/browser/components/preferences/in-content/tests/browser_contentblocking.js
@@ -1,26 +1,28 @@
 /* eslint-env webextensions */
 
 const CB_PREF = "browser.contentblocking.enabled";
+const CB_UI_PREF = "browser.contentblocking.ui.enabled";
 const CB_FB_UI_PREF = "browser.contentblocking.fastblock.ui.enabled";
 const CB_TP_UI_PREF = "browser.contentblocking.trackingprotection.ui.enabled";
 const CB_RT_UI_PREF = "browser.contentblocking.rejecttrackers.ui.enabled";
 const TP_PREF = "privacy.trackingprotection.enabled";
 const TP_PBM_PREF = "privacy.trackingprotection.pbmode.enabled";
 const TP_LIST_PREF = "urlclassifier.trackingTable";
 const FB_PREF = "browser.fastblock.enabled";
 const NCB_PREF = "network.cookie.cookieBehavior";
 const TOGGLE_PREF = "browser.contentblocking.global-toggle.enabled";
 
 requestLongerTimeout(2);
 
 // Checks that the content blocking toggle follows and changes the CB pref.
 add_task(async function testContentBlockingToggle() {
   SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
     [TOGGLE_PREF, true],
   ]});
 
   await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
   let doc = gBrowser.contentDocument;
 
   let contentBlockingToggle = doc.getElementById("contentBlockingToggle");
   let contentBlockingCheckbox = doc.getElementById("contentBlockingCheckbox");
@@ -53,16 +55,20 @@ add_task(async function testContentBlock
   is(contentBlockingToggle.getAttribute("aria-pressed"), "false", "toggle button has correct aria attribute");
 
   Services.prefs.clearUserPref(CB_PREF);
   gBrowser.removeCurrentTab();
 });
 
 // Tests that the content blocking main category checkboxes have the correct default state.
 add_task(async function testContentBlockingMainCategory() {
+  SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
+  ]});
+
   let prefs = [
     [CB_PREF, true],
     [FB_PREF, true],
     [TP_PREF, false],
     [TP_PBM_PREF, true],
     [NCB_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
   ];
 
@@ -150,16 +156,20 @@ add_task(async function testContentBlock
 
   for (let pref of prefs) {
     SpecialPowers.clearUserPref(pref[0]);
   }
 });
 
 // Tests that the content blocking "Restore Defaults" button does what it's supposed to.
 add_task(async function testContentBlockingRestoreDefaults() {
+  SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
+  ]});
+
   let prefs = {
     CB_PREF: null,
     FB_PREF: null,
     TP_LIST_PREF: null,
     TP_PREF: null,
     TP_PBM_PREF: null,
     NCB_PREF: null,
   };
@@ -212,16 +222,20 @@ add_task(async function testContentBlock
   }
 
   gBrowser.removeCurrentTab();
 });
 
 // Tests that the content blocking "Restore Defaults" button does not restore prefs
 // that are controlled by extensions.
 add_task(async function testContentBlockingRestoreDefaultsSkipExtensionControlled() {
+  SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
+  ]});
+
   function background() {
     browser.privacy.websites.trackingProtectionMode.set({value: "always"});
   }
 
   // Install an extension that sets Tracking Protection.
   let extension = ExtensionTestUtils.loadExtension({
     useAddonManager: "permanent",
     manifest: {
@@ -371,16 +385,17 @@ async function doDependentControlChecks(
   gBrowser.removeCurrentTab();
 }
 
 // Checks that the granular controls are disabled or enabled depending on the master pref for CB.
 add_task(async function testContentBlockingDependentControls() {
   // In Accept All Cookies mode, the radiogroup under Third-Party Cookies is always disabled
   // since the checkbox next to Third-Party Cookies would be unchecked.
   SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
     [CB_FB_UI_PREF, true],
     [CB_TP_UI_PREF, true],
     [CB_RT_UI_PREF, true],
     [NCB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT],
   ]});
 
   let dependentControls = [
     ".content-blocking-checkbox",
@@ -397,16 +412,17 @@ add_task(async function testContentBlock
     "#blockCookiesMenu",
   ];
 
   await doDependentControlChecks(dependentControls, alwaysDisabledControls);
 
   // In Block Cookies from Trackers (or Block Cookies from All Third-Parties) mode, the
   // radiogroup's disabled status must obey the content blocking enabled state.
   SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
     [CB_FB_UI_PREF, true],
     [CB_TP_UI_PREF, true],
     [CB_RT_UI_PREF, true],
     [NCB_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
   ]});
 
   dependentControls = [
     ".content-blocking-checkbox",
@@ -422,16 +438,17 @@ add_task(async function testContentBlock
   ];
 
   await doDependentControlChecks(dependentControls);
 });
 
 // Checks that the controls for tracking protection are disabled when all TP prefs are off.
 add_task(async function testContentBlockingDependentTPControls() {
   SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
     [CB_FB_UI_PREF, true],
     [CB_TP_UI_PREF, true],
     [CB_RT_UI_PREF, true],
     [TP_PREF, false],
     [TP_PBM_PREF, false],
     [NCB_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
   ]});
 
@@ -459,16 +476,17 @@ add_task(async function testContentBlock
 // when the Cookies and Site Data section is set to block either "All Cookies" or "Cookies from
 // unvisited websites".
 add_task(async function testContentBlockingDependentControlsOnSiteDataUI() {
   let prefValuesToTest = [
     Ci.nsICookieService.BEHAVIOR_REJECT,        // Block All Cookies
   ];
   for (let value of prefValuesToTest) {
     await SpecialPowers.pushPrefEnv({set: [
+      [CB_UI_PREF, true],
       [CB_FB_UI_PREF, true],
       [CB_TP_UI_PREF, true],
       [CB_RT_UI_PREF, true],
       [TP_PREF, false],
       [TP_PBM_PREF, true],
       [NCB_PREF, value],
     ]});
 
@@ -502,16 +520,17 @@ add_task(async function testContentBlock
 
   // When Block Cookies from unvisited websites is selected, the Third-Party Cookies section under
   // Content Blocking should get disabled unconditionally.
   prefValuesToTest = [
     Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN, // Block Cookies from unvisited websites
   ];
   for (let value of prefValuesToTest) {
     await SpecialPowers.pushPrefEnv({set: [
+      [CB_UI_PREF, true],
       [CB_FB_UI_PREF, true],
       [CB_TP_UI_PREF, true],
       [CB_RT_UI_PREF, true],
       [TP_PREF, false],
       [TP_PBM_PREF, true],
       [NCB_PREF, value],
     ]});
 
@@ -543,16 +562,17 @@ add_task(async function testContentBlock
   // When Accept All Cookies is selected, the radio buttons under Third-Party Cookies
   // in Content Blocking as well as the Type blocked controls in Cookies and Site Data
   // must remain disabled unconditionally.
   prefValuesToTest = [
     Ci.nsICookieService.BEHAVIOR_ACCEPT,         // Accept All Cookies
   ];
   for (let value of prefValuesToTest) {
     await SpecialPowers.pushPrefEnv({set: [
+      [CB_UI_PREF, true],
       [CB_FB_UI_PREF, true],
       [CB_TP_UI_PREF, true],
       [CB_RT_UI_PREF, true],
       [TP_PREF, false],
       [TP_PBM_PREF, true],
       [NCB_PREF, value],
     ]});
 
@@ -579,16 +599,17 @@ add_task(async function testContentBlock
   // For other choices of cookie policies, no parts of the UI should get disabled
   // unconditionally.
   prefValuesToTest = [
     Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, // Block All Third-Party Cookies
     Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER, // Block Cookies from third-party trackers
   ];
   for (let value of prefValuesToTest) {
     await SpecialPowers.pushPrefEnv({set: [
+      [CB_UI_PREF, true],
       [CB_FB_UI_PREF, true],
       [CB_TP_UI_PREF, true],
       [CB_RT_UI_PREF, true],
       [TP_PREF, false],
       [TP_PBM_PREF, true],
       [NCB_PREF, value],
     ]});
 
@@ -612,16 +633,17 @@ add_task(async function testContentBlock
 });
 
 
 // Checks that the warnings in the Content Blocking Third-Party Cookies section correctly appear based on
 // the selections in the Cookies and Site Data section.
 add_task(async function testContentBlockingThirdPartyCookiesWarning() {
   await SpecialPowers.pushPrefEnv({set: [
     [CB_PREF, true],
+    [CB_UI_PREF, true],
     [CB_FB_UI_PREF, true],
     [CB_TP_UI_PREF, true],
     [CB_RT_UI_PREF, true],
   ]});
 
   let expectedDeckIndex = new Map([
     [Ci.nsICookieService.BEHAVIOR_ACCEPT, 0],
     [Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, 0],
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -583,58 +583,79 @@ add_task(async function testExtensionCon
   // Don't finalize the current store since it will write out the bad data.
   await ExtensionSettingsStore._reloadFile(false);
 
   is(ExtensionSettingsStore.getSetting("prefs", "homepage_override"), null,
      "The ExtensionSettingsStore is left empty.");
 });
 
 add_task(async function testExtensionControlledTrackingProtection() {
+  const CB_UI_PREF = "browser.contentblocking.ui.enabled";
   const TP_PREF = "privacy.trackingprotection.enabled";
   const TP_DEFAULT = false;
   const EXTENSION_ID = "@set_tp";
-  const CONTROLLED_LABEL_ID = "contentBlockingTrackingProtectionExtensionContentLabel";
-  const CONTROLLED_BUTTON_ID = "contentBlockingDisableTrackingProtectionExtension";
-  const DISABLE_BUTTON_ID = "contentBlockingDisableTrackingProtectionExtension";
+  const CONTROLLED_LABEL_ID = {
+    old: "trackingProtectionExtensionContentLabel",
+    new: "contentBlockingTrackingProtectionExtensionContentLabel",
+  };
+  const CONTROLLED_BUTTON_ID = {
+    old: "trackingProtectionExtensionContentButton",
+    new: "contentBlockingDisableTrackingProtectionExtension",
+  };
+  const DISABLE_BUTTON_ID = {
+    old: "disableTrackingProtectionExtension",
+    new: "contentBlockingDisableTrackingProtectionExtension",
+  };
 
   let tpEnabledPref = () => Services.prefs.getBoolPref(TP_PREF);
+  let cbUIEnabledPref = () => Services.prefs.getBoolPref(CB_UI_PREF);
 
   await SpecialPowers.pushPrefEnv(
-    {"set": [[TP_PREF, TP_DEFAULT]]});
+    {"set": [[TP_PREF, TP_DEFAULT], [CB_UI_PREF, true]]});
 
   function background() {
     browser.privacy.websites.trackingProtectionMode.set({value: "always"});
   }
 
   function verifyState(isControlled) {
     is(tpEnabledPref(), isControlled, "TP pref is set to the expected value.");
 
-    let controlledLabel = doc.getElementById(CONTROLLED_LABEL_ID);
-    let controlledButton = doc.getElementById(CONTROLLED_BUTTON_ID);
+    let controlledLabel = doc.getElementById(CONTROLLED_LABEL_ID[uiType]);
+    let controlledButton = doc.getElementById(CONTROLLED_BUTTON_ID[uiType]);
 
     is(controlledLabel.hidden, !isControlled, "The extension controlled row's visibility is as expected.");
     is(controlledButton.hidden, !isControlled, "The disable extension button's visibility is as expected.");
     if (isControlled) {
       let controlledDesc = controlledLabel.querySelector("description");
       Assert.deepEqual(doc.l10n.getAttributes(controlledDesc), {
-        id: "extension-controlled-websites-content-blocking-all-trackers",
+        id: cbUIEnabledPref() ? "extension-controlled-websites-content-blocking-all-trackers" :
+                                "extension-controlled-websites-tracking-protection-mode",
         args: {
           name: "set_tp",
         },
       }, "The user is notified that an extension is controlling TP.");
     }
 
-    is(doc.getElementById("trackingProtectionMenu").disabled,
-       isControlled,
-       "TP control is enabled.");
+    if (uiType === "old") {
+      for (let element of doc.querySelectorAll("#trackingProtectionRadioGroup > radio")) {
+        is(element.disabled, isControlled, "TP controls are enabled.");
+      }
+      is(doc.querySelector("#trackingProtectionDesc > label").disabled,
+         isControlled,
+         "TP control label is enabled.");
+    } else {
+      is(doc.getElementById("trackingProtectionMenu").disabled,
+         isControlled,
+         "TP control is enabled.");
+    }
   }
 
   async function disableViaClick() {
-    let labelId = CONTROLLED_LABEL_ID;
-    let disableId = DISABLE_BUTTON_ID;
+    let labelId = CONTROLLED_LABEL_ID[uiType];
+    let disableId = DISABLE_BUTTON_ID[uiType];
     let controlledLabel = doc.getElementById(labelId);
 
     let enableMessageShown = waitForEnableMessage(labelId);
     doc.getElementById(disableId).click();
     await enableMessageShown;
 
     // The user is notified how to enable the extension.
     let controlledDesc = controlledLabel.querySelector("description");
@@ -644,21 +665,23 @@ add_task(async function testExtensionCon
 
     // The user can dismiss the enable instructions.
     let hidden = waitForMessageHidden(labelId);
     controlledLabel.querySelector("image:last-of-type").click();
     await hidden;
   }
 
   async function reEnableExtension(addon) {
-    let controlledMessageShown = waitForMessageShown(CONTROLLED_LABEL_ID);
+    let controlledMessageShown = waitForMessageShown(CONTROLLED_LABEL_ID[uiType]);
     await addon.enable();
     await controlledMessageShown;
   }
 
+  let uiType = "new";
+
   await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
   let doc = gBrowser.contentDocument;
 
   is(gBrowser.currentURI.spec, "about:preferences#privacy",
    "#privacy should be in the URI for about:preferences");
 
   verifyState(false);
 
@@ -668,27 +691,48 @@ add_task(async function testExtensionCon
     manifest: {
       name: "set_tp",
       applications: {gecko: {id: EXTENSION_ID}},
       permissions: ["privacy"],
     },
     background,
   });
 
-  let messageShown = waitForMessageShown(CONTROLLED_LABEL_ID);
+  let messageShown = waitForMessageShown(CONTROLLED_LABEL_ID[uiType]);
   await extension.startup();
   await messageShown;
   let addon = await AddonManager.getAddonByID(EXTENSION_ID);
 
   verifyState(true);
 
   await disableViaClick();
 
   verifyState(false);
 
+  // Switch to the "old" Tracking Protection UI.
+  uiType = "old";
+  Services.prefs.setBoolPref(CB_UI_PREF, false);
+
+  let browserLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, "about:preferences#privacy");
+  gBrowser.selectedBrowser.reload();
+  await browserLoaded;
+  is(gBrowser.currentURI.spec, "about:preferences#privacy",
+   "#privacy should be in the URI for about:preferences");
+  doc = gBrowser.contentDocument;
+
+  verifyState(false);
+
+  await reEnableExtension(addon);
+
+  verifyState(true);
+
+  await disableViaClick();
+
+  verifyState(false);
+
   // Enable the extension so we get the UNINSTALL event, which is needed by
   // ExtensionPreferencesManager to clean up properly.
   // TODO: BUG 1408226
   await reEnableExtension(addon);
 
   await extension.unload();
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
--- a/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_6.js
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_6.js
@@ -13,16 +13,25 @@ add_task(async function() {
  * Test for searching for the "Block Lists" subdialog.
  */
 add_task(async function() {
   async function doTest() {
     await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
     await evaluateSearchResults("block Web elements", "trackingGroup");
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["browser.contentblocking.ui.enabled", true],
+  ]});
+  info("Run the test with Content Blocking UI enabled");
+  await doTest();
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["browser.contentblocking.ui.enabled", false],
+  ]});
+  info("Run the test with Content Blocking UI disabled");
   await doTest();
 });
 
 /**
  * Test for searching for the "Allowed Sites - Pop-ups" subdialog.
  */
 add_task(async function() {
   await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
--- a/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_site_data.js
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_site_data.js
@@ -2,16 +2,53 @@
 * This file contains tests for the Preferences search bar.
 */
 
 // Enabling Searching functionatily. Will display search bar form this testcase forward.
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
 });
 
+// First, run the tests without the Content Blocking UI.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.contentblocking.ui.enabled", false]]});
+});
+
+/**
+ * Test for searching for the "Settings - Site Data" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await evaluateSearchResults("cookies", ["siteDataGroup"]);
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await evaluateSearchResults("site data", ["siteDataGroup"]);
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await evaluateSearchResults("cache", ["siteDataGroup"]);
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  await evaluateSearchResults("third-party", "siteDataGroup");
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+// Now, run the tests with the Content Blocking UI.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.contentblocking.ui.enabled", true]]});
+});
+
 /**
  * Test for searching for the "Settings - Site Data" subdialog.
  */
 add_task(async function() {
   await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
   await evaluateSearchResults("cookies", ["siteDataGroup", "trackingGroup"]);
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
--- a/browser/components/preferences/in-content/tests/browser_spotlight.js
+++ b/browser/components/preferences/in-content/tests/browser_spotlight.js
@@ -48,16 +48,17 @@ add_task(async function test_form_autofi
   is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "form-autofill",
     "The form-autofill section is spotlighted.");
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function test_change_cookie_settings() {
   await SpecialPowers.pushPrefEnv({set: [
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.contentblocking.fastblock.ui.enabled", true],
     ["browser.contentblocking.trackingprotection.ui.enabled", true],
     ["browser.contentblocking.rejecttrackers.ui.enabled", true],
   ]});
   let prefs = await openPreferencesViaOpenPreferencesAPI("privacy-trackingprotection", {leaveOpen: true});
   is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default");
   let doc = gBrowser.contentDocument;
   is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
@@ -1,28 +1,49 @@
 /* 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/. */
 
 /* eslint-env mozilla/frame-script */
 
 const CB_ENABLED_PREF = "browser.contentblocking.enabled";
+const CB_UI_ENABLED_PREF = "browser.contentblocking.ui.enabled";
 const TP_ENABLED_PREF = "privacy.trackingprotection.enabled";
 const TP_PB_ENABLED_PREF = "privacy.trackingprotection.pbmode.enabled";
 
+let contentBlockingUIEnabled = false;
+
 function updateTPInfo() {
   let tpButton = document.getElementById("tpButton");
   let tpToggle = document.getElementById("tpToggle");
+  let title = document.getElementById("title");
+  let titleTracking = document.getElementById("titleTracking");
   let tpSubHeader = document.getElementById("tpSubHeader");
 
+  let tpTitle = document.getElementById("tpTitle");
+  let cbTitle = document.getElementById("cbTitle");
+  let tpDescription = document.getElementById("tpDescription");
+  let cbDescription = document.getElementById("cbDescription");
+
+  tpTitle.toggleAttribute("hidden", contentBlockingUIEnabled);
+  tpDescription.toggleAttribute("hidden", contentBlockingUIEnabled);
+
+  cbTitle.toggleAttribute("hidden", !contentBlockingUIEnabled);
+  cbDescription.toggleAttribute("hidden", !contentBlockingUIEnabled);
+
   let globalTrackingEnabled = RPMGetBoolPref(TP_ENABLED_PREF);
   let trackingEnabled = globalTrackingEnabled || RPMGetBoolPref(TP_PB_ENABLED_PREF);
 
-  let contentBlockingEnabled = RPMGetBoolPref(CB_ENABLED_PREF);
-  trackingEnabled = trackingEnabled && contentBlockingEnabled;
+  if (contentBlockingUIEnabled) {
+    let contentBlockingEnabled = RPMGetBoolPref(CB_ENABLED_PREF);
+    trackingEnabled = trackingEnabled && contentBlockingEnabled;
+  } else {
+    title.toggleAttribute("hidden", trackingEnabled);
+    titleTracking.toggleAttribute("hidden", !trackingEnabled);
+  }
 
   // if tracking protection is enabled globally we don't even give the user
   // a choice here by hiding the toggle completely.
   tpButton.toggleAttribute("hidden", globalTrackingEnabled);
   tpToggle.checked = trackingEnabled;
 
   tpSubHeader.classList.toggle("tp-off", !trackingEnabled);
 }
@@ -32,36 +53,39 @@ document.addEventListener("DOMContentLoa
     document.documentElement.classList.remove("private");
     document.documentElement.classList.add("normal");
     document.getElementById("startPrivateBrowsing").addEventListener("click", function() {
       RPMSendAsyncMessage("OpenPrivateWindow");
     });
     return;
   }
 
+  contentBlockingUIEnabled = RPMGetBoolPref(CB_UI_ENABLED_PREF);
+
   document.getElementById("startTour").addEventListener("click", function() {
     RPMSendAsyncMessage("DontShowIntroPanelAgain");
   });
 
   let introURL = RPMGetFormatURLPref("privacy.trackingprotection.introURL");
-  // Variation 1 is specific to the Content Blocking UI.
-  let variation = "?variation=1";
+  // If the CB UI is enabled, tell the tour page to show a different variation
+  // that is updated to reflect the CB control center UI.
+  let variation = "?variation=" + (contentBlockingUIEnabled ? "1" : "0");
 
   document.getElementById("startTour").setAttribute("href", introURL + variation);
 
   document.getElementById("learnMore").setAttribute("href",
     RPMGetFormatURLPref("app.support.baseURL") + "private-browsing");
 
   let tpToggle = document.getElementById("tpToggle");
   document.getElementById("tpButton").addEventListener("click", () => {
     tpToggle.click();
   });
   tpToggle.addEventListener("change", async function() {
     let promises = [];
-    if (tpToggle.checked) {
+    if (tpToggle.checked && contentBlockingUIEnabled) {
       promises.push(RPMSetBoolPref(CB_ENABLED_PREF, true));
     }
 
     promises.push(RPMSetBoolPref(TP_PB_ENABLED_PREF, tpToggle.checked));
 
     await Promise.all(promises);
 
     updateTPInfo();
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -29,16 +29,17 @@
   <body dir="&locale.dir;">
     <p class="showNormal">&aboutPrivateBrowsing.notPrivate;</p>
     <button id="startPrivateBrowsing"
             class="showNormal"
             accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;">&privatebrowsingpage.openPrivateWindow.label;</button>
     <div class="showPrivate container">
       <h1 class="title">
         <span id="title">&privateBrowsing.title;</span>
+        <span id="titleTracking" hidden="hidden">&privateBrowsing.title.tracking;</span>
       </h1>
       <section class="section-main">
         <p>&aboutPrivateBrowsing.info.notsaved.before;<strong>&aboutPrivateBrowsing.info.notsaved.emphasize;</strong>&aboutPrivateBrowsing.info.notsaved.after;</p>
         <div class="list-row">
           <ul>
             <li>&aboutPrivateBrowsing.info.visited;</li>
             <li>&aboutPrivateBrowsing.info.cookies;</li>
             <li>&aboutPrivateBrowsing.info.searches;</li>
@@ -52,22 +53,24 @@
             <li>&aboutPrivateBrowsing.info.downloads;</li>
             <li>&aboutPrivateBrowsing.info.clipboard;</li>
           </ul>
         </div>
         <p>&aboutPrivateBrowsing.note.before;<strong>&aboutPrivateBrowsing.note.emphasize;</strong>&aboutPrivateBrowsing.note.after;</p>
       </section>
 
       <h2 id="tpSubHeader" class="about-subheader">
+        <span id="tpTitle">&trackingProtection.title;</span>
         <span id="cbTitle">&contentBlocking.title;</span>
         <input id="tpToggle" class="toggle toggle-input" type="checkbox"/>
         <span id="tpButton" class="toggle-btn"></span>
       </h2>
 
       <section class="section-main">
+        <p id="tpDescription">&trackingProtection.description2;</p>
         <p id="cbDescription">&contentBlocking.description;</p>
         <p>
           <a id="startTour" class="button">&trackingProtection.startTour1;</a>
         </p>
       </section>
 
       <section class="section-main">
         <p class="about-info">&aboutPrivateBrowsing.learnMore3.before;<a id="learnMore" target="_blank">&aboutPrivateBrowsing.learnMore3.title;</a>&aboutPrivateBrowsing.learnMore3.after;</p>
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
@@ -1,14 +1,15 @@
 /* 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/. */
 
 const TP_PB_ENABLED_PREF = "privacy.trackingprotection.pbmode.enabled";
 const CB_ENABLED_PREF = "browser.contentblocking.enabled";
+const CB_UI_ENABLED_PREF = "browser.contentblocking.ui.enabled";
 
 /**
  * Opens a new private window and loads "about:privatebrowsing" there.
  */
 async function openAboutPrivateBrowsing() {
   let win = await BrowserTestUtils.openNewBrowserWindow({
     private: true,
     waitForTabURL: "about:privatebrowsing",
@@ -48,17 +49,46 @@ async function testLinkOpensUrl({ win, t
 /**
  * Tests the links in "about:privatebrowsing".
  */
 add_task(async function test_links() {
   // Use full version and change the remote URLs to prevent network access.
   Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
   Services.prefs.setCharPref("privacy.trackingprotection.introURL",
                              "https://example.com/tour");
+  Services.prefs.setBoolPref(CB_UI_ENABLED_PREF, false);
   registerCleanupFunction(function() {
+    Services.prefs.clearUserPref(CB_UI_ENABLED_PREF);
+    Services.prefs.clearUserPref("privacy.trackingprotection.introURL");
+    Services.prefs.clearUserPref("app.support.baseURL");
+  });
+
+  let { win, tab } = await openAboutPrivateBrowsing();
+
+  await testLinkOpensTab({ win, tab,
+    elementId: "learnMore",
+    expectedUrl: "https://example.com/private-browsing",
+  });
+
+  await testLinkOpensUrl({ win, tab,
+    elementId: "startTour",
+    expectedUrl: "https://example.com/tour?variation=0",
+  });
+
+  await BrowserTestUtils.closeWindow(win);
+});
+
+add_task(async function test_links_CB() {
+  // Use full version and change the remote URLs to prevent network access.
+  Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
+  Services.prefs.setCharPref("privacy.trackingprotection.introURL",
+                             "https://example.com/tour");
+  Services.prefs.setBoolPref(CB_UI_ENABLED_PREF, true);
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref(CB_UI_ENABLED_PREF);
     Services.prefs.clearUserPref("privacy.trackingprotection.introURL");
     Services.prefs.clearUserPref("app.support.baseURL");
   });
 
   let { win, tab } = await openAboutPrivateBrowsing();
 
   await testLinkOpensTab({ win, tab,
     elementId: "learnMore",
@@ -83,25 +113,67 @@ function waitForPrefChanged(pref) {
       },
     };
     Services.prefs.addObserver(pref, prefObserver);
   });
 }
 
 /**
  * Tests the action to disable and re-enable Tracking Protection in
+ * "about:privatebrowsing".
+ */
+add_task(async function test_toggleTrackingProtection() {
+  // Use tour version but disable Tracking Protection.
+  Services.prefs.setBoolPref(TP_PB_ENABLED_PREF, true);
+  // For good measure, check that content blocking being off
+  // has no impact if the contentblocking UI is not shown.
+  Services.prefs.setBoolPref(CB_ENABLED_PREF, false);
+  Services.prefs.setBoolPref(CB_UI_ENABLED_PREF, false);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref(TP_PB_ENABLED_PREF);
+    Services.prefs.clearUserPref(CB_ENABLED_PREF);
+    Services.prefs.clearUserPref(CB_UI_ENABLED_PREF);
+  });
+
+  let { win, tab } = await openAboutPrivateBrowsing();
+
+  // Set up the observer for the preference change before triggering the action.
+  let promisePrefChanged = waitForPrefChanged(TP_PB_ENABLED_PREF);
+  await ContentTask.spawn(tab, {}, async function() {
+    is(content.document.getElementById("tpToggle").checked, true, "toggle is active");
+    content.document.getElementById("tpButton").click();
+  });
+  await promisePrefChanged;
+  ok(!Services.prefs.getBoolPref(TP_PB_ENABLED_PREF), "Tracking Protection is disabled.");
+
+  promisePrefChanged = waitForPrefChanged(TP_PB_ENABLED_PREF);
+  await ContentTask.spawn(tab, {}, async function() {
+    is(content.document.getElementById("tpToggle").checked, false, "toggle is not active");
+    content.document.getElementById("tpButton").click();
+  });
+  await promisePrefChanged;
+  ok(Services.prefs.getBoolPref(TP_PB_ENABLED_PREF), "Tracking Protection is enabled.");
+
+  await BrowserTestUtils.closeWindow(win);
+});
+
+/**
+ * Tests the action to disable and re-enable Tracking Protection in
  * "about:privatebrowsing" when content blocking is disabled.
  */
 add_task(async function test_toggleTrackingProtectionContentBlocking() {
   Services.prefs.setBoolPref(TP_PB_ENABLED_PREF, true);
   Services.prefs.setBoolPref(CB_ENABLED_PREF, false);
+  Services.prefs.setBoolPref(CB_UI_ENABLED_PREF, true);
 
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref(TP_PB_ENABLED_PREF);
     Services.prefs.clearUserPref(CB_ENABLED_PREF);
+    Services.prefs.clearUserPref(CB_UI_ENABLED_PREF);
   });
 
   let { win, tab } = await openAboutPrivateBrowsing();
 
   let promiseCBPrefChanged = waitForPrefChanged(CB_ENABLED_PREF);
   await ContentTask.spawn(tab, {}, async function() {
     is(content.document.getElementById("tpToggle").checked, false, "toggle is not active");
     content.document.getElementById("tpButton").click();
--- a/browser/components/uitour/test/browser_contentBlocking.js
+++ b/browser/components/uitour/test/browser_contentBlocking.js
@@ -1,37 +1,37 @@
 "use strict";
 
 const PREF_INTRO_COUNT = "browser.contentblocking.introCount";
-const PREF_CB_ENABLED = "browser.contentblocking.enabled";
+const PREF_CB_UI_ENABLED = "browser.contentblocking.ui.enabled";
 const PREF_TP_ENABLED = "privacy.trackingprotection.enabled";
 const PREF_FB_ENABLED = "browser.fastblock.enabled";
 const PREF_FB_TIMEOUT = "browser.fastblock.timeout";
 const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 const TOOLTIP_PANEL = document.getElementById("UITourTooltip");
 const TOOLTIP_ANCHOR = document.getElementById("tracking-protection-icon-animatable-box");
 
 var {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
 
 registerCleanupFunction(function() {
   UrlClassifierTestUtils.cleanupTestTrackers();
-  Services.prefs.clearUserPref(PREF_CB_ENABLED);
+  Services.prefs.clearUserPref(PREF_CB_UI_ENABLED);
   Services.prefs.clearUserPref(PREF_TP_ENABLED);
   Services.prefs.clearUserPref(PREF_FB_ENABLED);
   Services.prefs.clearUserPref(PREF_FB_TIMEOUT);
   Services.prefs.clearUserPref(PREF_INTRO_COUNT);
 });
 
 function allowOneIntro() {
   Services.prefs.setIntPref(PREF_INTRO_COUNT, window.ContentBlocking.MAX_INTROS - 1);
 }
 
 add_task(async function setup_test() {
-  Services.prefs.setBoolPref(PREF_CB_ENABLED, true);
+  Services.prefs.setBoolPref(PREF_CB_UI_ENABLED, true);
   Services.prefs.setBoolPref(PREF_TP_ENABLED, true);
   await UrlClassifierTestUtils.addTestTrackers();
 });
 
 add_task(async function test_benignPage() {
   info("Load a test page not containing tracking elements");
   allowOneIntro();
   await BrowserTestUtils.withNewTab(BENIGN_PAGE, async function() {
--- a/browser/components/uitour/test/browser_trackingProtection.js
+++ b/browser/components/uitour/test/browser_trackingProtection.js
@@ -1,32 +1,33 @@
 "use strict";
 
-const PREF_INTRO_COUNT = "browser.contentblocking.introCount";
-const PREF_CB_ENABLED = "browser.contentblocking.enabled";
+const PREF_INTRO_COUNT = "privacy.trackingprotection.introCount";
+const PREF_CB_UI_ENABLED = "browser.contentblocking.ui.enabled";
 const PREF_TP_ENABLED = "privacy.trackingprotection.enabled";
 const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 const TOOLTIP_PANEL = document.getElementById("UITourTooltip");
 const TOOLTIP_ANCHOR = document.getElementById("tracking-protection-icon-animatable-box");
 
 var {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
 
 registerCleanupFunction(function() {
   UrlClassifierTestUtils.cleanupTestTrackers();
-  Services.prefs.clearUserPref(PREF_CB_ENABLED);
+  Services.prefs.clearUserPref(PREF_CB_UI_ENABLED);
   Services.prefs.clearUserPref(PREF_TP_ENABLED);
+  Services.prefs.clearUserPref(PREF_INTRO_COUNT);
 });
 
 function allowOneIntro() {
   Services.prefs.setIntPref(PREF_INTRO_COUNT, window.ContentBlocking.MAX_INTROS - 1);
 }
 
 add_task(async function setup_test() {
-  Services.prefs.setBoolPref(PREF_CB_ENABLED, true);
+  Services.prefs.setBoolPref(PREF_CB_UI_ENABLED, false);
   Services.prefs.setBoolPref(PREF_TP_ENABLED, true);
   await UrlClassifierTestUtils.addTestTrackers();
 });
 
 add_task(async function test_benignPage() {
   info("Load a test page not containing tracking elements");
   allowOneIntro();
   await BrowserTestUtils.withNewTab({gBrowser, url: BENIGN_PAGE}, async function() {
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -1,14 +1,16 @@
 # 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/.
 
 do-not-track-description = Send websites a “Do Not Track” signal that you don’t want to be tracked
 do-not-track-learn-more = Learn more
+do-not-track-option-default =
+    .label = Only when using Tracking Protection
 do-not-track-option-default-content-blocking =
     .label = Only when { -brand-short-name } is set to block Detected Trackers
 do-not-track-option-always =
     .label = Always
 
 pref-page =
     .title =
         { PLATFORM() ->
@@ -102,16 +104,20 @@ extension-controlled-web-notifications= 
 # This string is shown to notify the user that the default search engine
 # is being controlled by an extension.
 extension-controlled-default-search = An extension, <img data-l10n-name="icon"/> { $name }, has set your default search engine.
 
 # This string is shown to notify the user that Container Tabs
 # are being enabled by an extension.
 extension-controlled-privacy-containers = An extension, <img data-l10n-name="icon"/> { $name }, requires Container Tabs.
 
+# This string is shown to notify the user that their tracking protection preferences
+# are being controlled by an extension.
+extension-controlled-websites-tracking-protection-mode = An extension, <img data-l10n-name="icon"/> { $name }, is controlling tracking protection.
+
 # This string is shown to notify the user that their content blocking "All Detected Trackers"
 # preferences are being controlled by an extension.
 extension-controlled-websites-content-blocking-all-trackers = An extension, <img data-l10n-name="icon"/> { $name }, is controlling this setting.
 
 # This string is shown to notify the user that their proxy configuration preferences
 # are being controlled by an extension.
 extension-controlled-proxy-config = An extension, <img data-l10n-name="icon"/> { $name }, is controlling how { -brand-short-name } connects to the internet.
 
@@ -878,20 +884,40 @@ content-blocking-reject-trackers-block-t
   .label = Trackers
   .accesskey = k
 content-blocking-reject-trackers-all-third-parties-option =
   .label = All third-party cookies (may cause websites to break)
   .accesskey = A
 
 ## Privacy Section - Tracking
 
+tracking-header = Tracking Protection
+
+tracking-desc = Tracking Protection blocks online trackers that collect your browsing data across multiple websites. <a data-l10n-name="learn-more">Learn more about Tracking Protection and your privacy</a>
+
+tracking-mode-label = Use Tracking Protection to block known trackers
+
+tracking-mode-always =
+    .label = Always
+    .accesskey = y
+tracking-mode-private =
+    .label = Only in private windows
+    .accesskey = l
+tracking-mode-never =
+    .label = Never
+    .accesskey = N
+
 tracking-exceptions =
     .label = Exceptions…
     .accesskey = x
 
+tracking-change-block-list =
+    .label = Change Block List…
+    .accesskey = C
+
 ## Privacy Section - Permissions
 
 permissions-header = Permissions
 
 permissions-location = Location
 permissions-location-settings =
     .label = Settings…
     .accesskey = t
--- a/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
@@ -2,16 +2,17 @@
    - 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/. -->
 
 <!ENTITY aboutPrivateBrowsing.notPrivate                 "You are currently not in a private window.">
 <!ENTITY privatebrowsingpage.openPrivateWindow.label     "Open a Private Window">
 <!ENTITY privatebrowsingpage.openPrivateWindow.accesskey "P">
 
 <!ENTITY privateBrowsing.title                           "Private Browsing">
+<!ENTITY privateBrowsing.title.tracking                  "Private Browsing with Tracking Protection">
 <!ENTITY aboutPrivateBrowsing.info.notsaved.before       "When you browse in a Private Window, Firefox ">
 <!ENTITY aboutPrivateBrowsing.info.notsaved.emphasize    "does not save">
 <!ENTITY aboutPrivateBrowsing.info.notsaved.after        ":">
 <!ENTITY aboutPrivateBrowsing.info.visited               "visited pages">
 <!ENTITY aboutPrivateBrowsing.info.searches              "searches">
 <!ENTITY aboutPrivateBrowsing.info.cookies               "cookies">
 <!ENTITY aboutPrivateBrowsing.info.temporaryFiles        "temporary files">
 <!ENTITY aboutPrivateBrowsing.info.saved.before          "Firefox ">
@@ -22,12 +23,14 @@
 <!ENTITY aboutPrivateBrowsing.info.clipboard             "copied text">
 <!ENTITY aboutPrivateBrowsing.note.before                "Private Browsing ">
 <!ENTITY aboutPrivateBrowsing.note.emphasize             "doesn’t make you anonymous">
 <!ENTITY aboutPrivateBrowsing.note.after                 " on the Internet. Your employer or Internet service provider can still know what page you visit.">
 <!ENTITY aboutPrivateBrowsing.learnMore3.before          "Learn more about ">
 <!ENTITY aboutPrivateBrowsing.learnMore3.title           "Private Browsing">
 <!ENTITY aboutPrivateBrowsing.learnMore3.after           ".">
 
+<!ENTITY trackingProtection.title                        "Tracking Protection">
+<!ENTITY trackingProtection.description2                 "Some websites use trackers that can monitor your activity across the Internet. With Tracking Protection Firefox will block many trackers that can collect information about your browsing behavior.">
 <!ENTITY trackingProtection.startTour1                   "See how it works">
 
 <!ENTITY contentBlocking.title                           "Content Blocking">
 <!ENTITY contentBlocking.description                     "Some websites use trackers that can monitor your activity across the Internet. In private windows, Firefox Content Blocking automatically blocks many trackers that can collect information about your browsing behavior.">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -1024,16 +1024,19 @@ you can use these alternative items. Oth
 <!ENTITY contentBlocking.breakageReportView.label "Report Problems">
 <!ENTITY contentBlocking.breakageReportView2.description "Content blocking can cause problems with some websites. When you report problems, you’ll help make &brandShortName; better for everyone. (This will send a URL as well as information about your browser settings to Mozilla.)">
 <!ENTITY contentBlocking.breakageReportView.learnMore "Learn More">
 <!ENTITY contentBlocking.breakageReportView.collection.url.label "URL">
 <!ENTITY contentBlocking.breakageReportView.collection.comments.label "What problems did you have? (Optional)">
 <!ENTITY contentBlocking.breakageReportView.sendReport.label "Send Report">
 <!ENTITY contentBlocking.breakageReportView.cancel.label "Cancel">
 
+<!ENTITY trackingProtection.title "Tracking Protection">
+<!ENTITY trackingProtection.tooltip "Open Tracking Protection Preferences">
+
 <!-- LOCALIZATION NOTE (trackingProtection.unblock3.label, trackingProtection.unblock3.accesskey):
      The associated button with this label and accesskey is only shown when opening the control
      center while looking at a site with trackers in NON-private browsing mode. -->
 <!ENTITY trackingProtection.unblock4.label "Disable Blocking For This Site">
 <!ENTITY trackingProtection.unblock4.accesskey "D">
 <!-- LOCALIZATION NOTE (trackingProtection.unblockPrivate3.label, trackingProtection.unblockPrivate3.accesskey):
      The associated button with this label and accesskey is only shown when opening the control
      center while looking at a site with trackers in PRIVATE browsing mode. -->
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -507,24 +507,35 @@ identity.extension.label=Extension (%S)
 identity.extension.tooltip=Loaded by extension: %S
 identity.showDetails.tooltip=Show connection details
 
 contentBlocking.title=Content Blocking
 contentBlocking.tooltip=Open Content Blocking Preferences
 contentBlocking.toggle.enable.tooltip=Enable Content Blocking
 contentBlocking.toggle.disable.tooltip=Disable Content Blocking
 
+trackingProtection.intro.title=How Tracking Protection works
+# LOCALIZATION NOTE (trackingProtection.intro.description2):
+# %S is brandShortName. This string should match the one from Step 1 of the tour
+# when it starts from the button shown when a new private window is opened.
+trackingProtection.intro.description2=When you see the shield, %S is blocking some parts of the page that could track your browsing activity.
+# LOCALIZATION NOTE (trackingProtection.intro.step1of3): Indicates that the intro panel is step one of three in a tour.
+trackingProtection.intro.step1of3=1 of 3
+trackingProtection.intro.nextButton.label=Next
+
 # LOCALIZATION NOTE (contentBlocking.intro.title): %S is brandShortName.
 contentBlocking.intro.title=New in %S: Content Blocking
 # LOCALIZATION NOTE (contentBlocking.v1.intro.description): %S is brandShortName.
 contentBlocking.intro.v1.description=When you see the shield, %S is blocking parts of the page that can slow your browsing or track you online.
 contentBlocking.intro.v2.description=The privacy benefits of Tracking Protection are now just one part of content blocking. When you see the shield, content blocking is on.
-# LOCALIZATION NOTE (trackingProtection.intro.step1of3): Indicates that the intro panel is step one of three in a tour.
-trackingProtection.intro.step1of3=1 of 3
-trackingProtection.intro.nextButton.label=Next
+
+trackingProtection.toggle.enable.tooltip=Enable Tracking Protection
+trackingProtection.toggle.disable.tooltip=Disable Tracking Protection
+trackingProtection.toggle.enable.pbmode.tooltip=Enable Tracking Protection in Private Browsing
+trackingProtection.toggle.disable.pbmode.tooltip=Disable Tracking Protection in Private Browsing
 
 trackingProtection.icon.activeTooltip=Tracking attempts blocked
 trackingProtection.icon.disabledTooltip=Tracking content detected
 
 # Edit Bookmark UI
 editBookmarkPanel.newBookmarkTitle=New Bookmark
 editBookmarkPanel.editBookmarkTitle=Edit This Bookmark
 editBookmarkPanel.cancel.label=Cancel
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -378,16 +378,25 @@ description#identity-popup-content-verif
 #identity-popup-breakageReportView-collection-comments {
   height: 120px;
 }
 
 #identity-popup-content-blocking-content {
   background-image: url("chrome://browser/skin/controlcenter/tracking-protection.svg");
 }
 
+/* We can currently show either the old tracking protection-only UI, which has "Tracking Protection"
+ * as a label, or the new content blocking UI which has a different label and also a list of
+ * categories of blockers. This rule hides elements depending on which UI we want to show */
+#identity-popup-content-blocking-content[contentBlockingUI] #tracking-protection-label,
+#identity-popup-content-blocking-content:not([contentBlockingUI]) #content-blocking-label,
+#identity-popup-content-blocking-content:not([contentBlockingUI]) > #identity-popup-content-blocking-category-list {
+  display: none;
+}
+
 /* Disabled label */
 
 #identity-popup-content-blocking-disabled-label {
   padding: 2px 5px;
   border-radius: 3px;
   margin: 5px;
   display: none;
   color: #fff;
@@ -405,16 +414,21 @@ description#identity-popup-content-verif
 }
 
 #identity-popup-content-blocking-content:not([enabled]) #identity-popup-content-blocking-disabled-label {
   display: -moz-box;
   background-color: #d70022;
   stroke: #d70022;
 }
 
+#identity-popup-content-blocking-content:not([contentBlockingUI]):not([enabled]) #identity-popup-content-blocking-disabled-label {
+  background-color: #b1b1b3;
+  stroke: #b1b1b3;
+}
+
 #identity-popup-content-blocking-content:not([enabled]) #identity-popup-content-blocking-disabled-label-exception {
   display: none;
 }
 
 #identity-popup-content-blocking-disabled-label > label {
   margin: 0;
 }
 
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -393,20 +393,28 @@ button > hbox > label {
   line-height: 30px;
 }
 
 #allowSmartSize {
   margin-top: 0;
   margin-bottom: 4px;
 }
 
+#trackingProtectionBox {
+  margin-top: 16px;
+}
+
 #doNotTrackLearnMoreBox {
   margin-top: 32px;
 }
 
+#trackingProtectionAdvancedSettings {
+  margin-inline-start: 15px;
+}
+
 #historyPane {
   margin-top: 4px;
 }
 
 #historyButtons {
   display: flex;
   flex-direction: column;
   justify-content: space-between;
--- a/browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css
+++ b/browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css
@@ -81,17 +81,18 @@ p {
 .about-subheader.tp-off {
   background-image: url("chrome://browser/skin/privatebrowsing/tracking-protection-off.svg");
 }
 
 .about-info {
   font-size: .9em;
 }
 
-#cbTitle {
+#cbTitle,
+#tpTitle {
   margin-inline-end: 12px;
 }
 
 a.button {
   padding: 3px 20px;
   background-color: #8000d7;
   border: 1px solid #6000a1;
   text-decoration: none;
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.jsm
@@ -23,16 +23,17 @@ const HTTP_PASSWORD_PAGE = `http://test2
 const MIXED_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed.html`;
 const MIXED_ACTIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_active.html`;
 const MIXED_PASSIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_passive.html`;
 const TRACKING_PAGE = `http://tracking.example.org/${RESOURCE_PATH}/tracking.html`;
 
 var ControlCenter = {
   init(libDir) {
     // Disable the FTU tours.
+    Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
     Services.prefs.setIntPref("browser.contentblocking.introCount", 20);
   },
 
   configurations: {
     about: {
       selectors: ["#navigator-toolbox", "#identity-popup"],
       async applyConfig() {
         await loadPage("about:rights");
--- a/dom/indexedDB/test/test_third_party.html
+++ b/dom/indexedDB/test/test_third_party.html
@@ -59,16 +59,17 @@
 
       if (!testRunning) {
         testRunning = true;
         iframe.addEventListener("load", iframeLoaded);
       }
       SpecialPowers.pushPrefEnv({
         "set": [
           ["browser.contentblocking.enabled", true],
+          ["browser.contentblocking.ui.enabled", true],
           ["network.cookie.cookieBehavior", testData[testIndex].cookieBehavior],
         ],
       }, () => {
         iframe.src = testData[testIndex].host + iframe1Path;
       });
       // SpecialPowers.setIntPref("network.cookie.cookieBehavior", testData[testIndex].cookieBehavior);
     }
 
--- a/dom/serviceworkers/test/test_third_party_iframes.html
+++ b/dom/serviceworkers/test/test_third_party_iframes.html
@@ -80,16 +80,17 @@ function runTest(aExpectedResponses) {
   };
 }
 
 // Verify that we can register and intercept a 3rd party iframe with
 // the given cookie policy.
 function testShouldIntercept(behavior, lifetime, done) {
   SpecialPowers.pushPrefEnv({"set": [
       ["browser.contentblocking.enabled", true],
+      ["browser.contentblocking.ui.enabled", true],
       ["network.cookie.cookieBehavior", behavior],
       ["network.cookie.lifetimePolicy", lifetime],
   ]}, function() {
     runTest([{
       status: "ok"
     }, {
       status: "registrationdone",
       next: function() {
--- a/dom/tests/mochitest/bugs/test_bug1171215.html
+++ b/dom/tests/mochitest/bugs/test_bug1171215.html
@@ -24,16 +24,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     // Set a cookie in example.org so we can test that we can't read it in
     // third-party cases.
     f.contentWindow.location =
         "http://example.org/tests/dom/tests/mochitest/bugs/file_prime_cookie.html";
     waitForLoad().then(function() {
         // Cookies are set up, disallow third-party cookies and start the test.
         SpecialPowers.pushPrefEnv({ set: [
             ["browser.contentblocking.enabled", true],
+            ["browser.contentblocking.ui.enabled", true],
             ["network.cookie.cookieBehavior", 1],
           ]}, () => { continueTest(); });
     }).catch((e) => { ok(false, `Got exception: ${e}`) });
   }
 
   function waitForLoad() {
     return new Promise((resolve) => {
       window.addEventListener("message", function(msg) {
--- a/dom/tests/mochitest/general/storagePermissionsUtils.js
+++ b/dom/tests/mochitest/general/storagePermissionsUtils.js
@@ -23,16 +23,17 @@ if (inFrame) {
   finishTest = function() {
     SimpleTest.finish();
   };
 }
 
 function setCookieBehavior(behavior) {
   return SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     [kPrefName, behavior],
   ]});
 }
 
 function runIFrame(url) {
   return new Promise((resolve, reject) => {
     function onMessage(e)  {
       if (e.data == "done") {
--- a/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html
@@ -12,16 +12,17 @@
 
 <script type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 // Set cookies behavior to "always reject".
 SpecialPowers.pushPrefEnv({"set": [
   ["browser.contentblocking.enabled", true],
+  ["browser.contentblocking.ui.enabled", true],
   ["network.cookie.cookieBehavior", 2],
 ]}, test1);
 
 function test1() {
   try {
     localStorage.setItem("contentkey", "test-value");
     ok(false, "Setting localStorageItem should throw a security exception");
   }
--- a/dom/workers/test/test_sharedWorker_thirdparty.html
+++ b/dom/workers/test/test_sharedWorker_thirdparty.html
@@ -43,16 +43,17 @@
     let result = await testThirdPartyFrame('allowed');
     ok(result === 'allowed',
        'SharedWorker should be allowed when 3rd party iframes can access storage');
   });
 
   add_task(async function blocked() {
     await SpecialPowers.pushPrefEnv({ set: [
       ["browser.contentblocking.enabled", true],
+      ["browser.contentblocking.ui.enabled", true],
       ["network.cookie.cookieBehavior", COOKIE_BEHAVIOR_REJECTFOREIGN]
     ]});
     let result = await testThirdPartyFrame('blocked');
     ok(result === 'blocked',
        'SharedWorker should not be allowed when 3rd party iframes are denied storage');
   });
 
   </script>
--- a/extensions/cookie/test/file_testcommon.js
+++ b/extensions/cookie/test/file_testcommon.js
@@ -10,16 +10,17 @@ var gScript;
 var gLoads = 0;
 
 function setupTest(uri, cookies, loads) {
   SimpleTest.waitForExplicitFinish();
 
   var prefSet = new Promise(resolve => {
     SpecialPowers.pushPrefEnv({ set: [
       ["browser.contentblocking.enabled", true],
+      ["browser.contentblocking.ui.enabled", true],
       ["network.cookie.cookieBehavior", 1],
     ]}, resolve);
   });
 
   gScript = SpecialPowers.loadChromeScript(SCRIPT_URL);
   gExpectedCookies = cookies;
   gExpectedLoads = loads;
 
--- a/extensions/cookie/test/unit/test_cookies_thirdparty.js
+++ b/extensions/cookie/test/unit/test_cookies_thirdparty.js
@@ -3,16 +3,17 @@
 
 // test third party cookie blocking, for the cases:
 // 1) with null channel
 // 2) with channel, but with no docshell parent
 
 function run_test() {
   // Set the needed content blocking prefs
   Services.prefs.setBoolPref("browser.contentblocking.enabled", true);
+  Services.prefs.setBoolPref("browser.contentblocking.ui.enabled", true);
 
   // Create URIs and channels pointing to foo.com and bar.com.
   // We will use these to put foo.com into first and third party contexts.
   var spec1 = "http://foo.com/foo.html";
   var spec2 = "http://bar.com/bar.html";
   var uri1 = NetUtil.newURI(spec1);
   var uri2 = NetUtil.newURI(spec2);
   var channel1 = NetUtil.newChannel({uri: uri1, loadUsingSystemPrincipal: true});
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -1631,16 +1631,23 @@ PREF("preferences.allow.omt-write", bool
 
 // Whether Content Blocking has been enabled.
 VARCACHE_PREF(
   "browser.contentblocking.enabled",
    browser_contentblocking_enabled,
   bool, true
 )
 
+// Whether Content Blocking UI has been enabled.
+VARCACHE_PREF(
+  "browser.contentblocking.ui.enabled",
+   browser_contentblocking_ui_enabled,
+  bool, true
+)
+
 // Whether Content Blocking Third-Party Cookies UI has been enabled.
 VARCACHE_PREF(
   "browser.contentblocking.allowlist.storage.enabled",
    browser_contentblocking_allowlist_storage_enabled,
   bool, false
 )
 
 VARCACHE_PREF(
--- a/toolkit/components/antitracking/test/browser/browser_backgroundImageAssertion.js
+++ b/toolkit/components/antitracking/test/browser/browser_backgroundImageAssertion.js
@@ -3,16 +3,17 @@ ChromeUtils.import("resource://gre/modul
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
--- a/toolkit/components/antitracking/test/browser/browser_existingCookiesForSubresources.js
+++ b/toolkit/components/antitracking/test/browser/browser_existingCookiesForSubresources.js
@@ -72,16 +72,17 @@ add_task(async function() {
 
   Services.perms.removeAll();
 
   // Now set up our prefs
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
   ]});
 
   info("Creating a new tab");
   tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
   gBrowser.selectedTab = tab;
 
   browser = gBrowser.getBrowserForTab(tab);
--- a/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
@@ -50,16 +50,17 @@ add_task(async function() {
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["privacy.trackingprotection.enabled", true],
     // the test doesn't open a private window, so we don't care about this pref's value
     ["privacy.trackingprotection.pbmode.enabled", false],
     // tracking annotations aren't needed in this test, only TP is needed
     ["privacy.trackingprotection.annotate_channels", false],
     // prevent the content blocking on-boarding UI to start mid-way through the test!
     [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
--- a/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
@@ -45,16 +45,17 @@ async function onModifyRequest() {
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["privacy.trackingprotection.enabled", true],
     // the test doesn't open a private window, so we don't care about this pref's value
     ["privacy.trackingprotection.pbmode.enabled", false],
     // tracking annotations aren't needed in this test, only TP is needed
     ["privacy.trackingprotection.annotate_channels", false],
     // prevent the content blocking on-boarding UI to start mid-way through the test!
     [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
--- a/toolkit/components/antitracking/test/browser/browser_script.js
+++ b/toolkit/components/antitracking/test/browser/browser_script.js
@@ -3,16 +3,17 @@ ChromeUtils.import("resource://gre/modul
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
--- a/toolkit/components/antitracking/test/browser/browser_storageAccessWithHeuristics.js
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessWithHeuristics.js
@@ -4,16 +4,17 @@ add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["dom.storage_access.enabled", true],
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
--- a/toolkit/components/antitracking/test/browser/browser_subResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_subResources.js
@@ -3,16 +3,17 @@ ChromeUtils.import("resource://gre/modul
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     ["browser.contentblocking.enabled", true],
+    ["browser.contentblocking.ui.enabled", true],
     ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
--- a/toolkit/components/remotepagemanager/MessagePort.jsm
+++ b/toolkit/components/remotepagemanager/MessagePort.jsm
@@ -22,16 +22,17 @@ ChromeUtils.defineModuleGetter(this, "Pr
 let RPMAccessManager = {
   accessMap: {
     "about:privatebrowsing": {
       // "sendAsyncMessage": handled within AboutPrivateBrowsingHandler.jsm
       // "setBoolPref": handled within AsyncPrefs.jsm and uses the prefs
       //                ["browser.contentblocking.enabled",
       //                 "privacy.trackingprotection.pbmode.enabled"],
       "getBoolPref": ["browser.contentblocking.enabled",
+                      "browser.contentblocking.ui.enabled",
                       "privacy.trackingprotection.enabled",
                       "privacy.trackingprotection.pbmode.enabled"],
       "getFormatURLPref": ["privacy.trackingprotection.introURL",
                            "app.support.baseURL"],
       "isWindowPrivate": ["yes"],
     },
   },