Merge inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Sat, 17 Nov 2018 23:37:07 +0200
changeset 446922 77223bb2fac278373dfcdde11fcda74b4c80aa61
parent 446917 a92c330bac8bce0c51099d630349aecbb71d7c35 (current diff)
parent 446921 f77121fb76fc00afa520b03f847c20e8baa88715 (diff)
child 446924 2d8c5d46389336d6c4620e947f757e302d3f224c
child 446933 572f525f1afe920d092830673f843066425d4494
push id35057
push userccoroiu@mozilla.com
push dateSat, 17 Nov 2018 21:37:33 +0000
treeherdermozilla-central@77223bb2fac2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
77223bb2fac2 / 65.0a1 / 20181117220111 / files
nightly linux64
77223bb2fac2 / 65.0a1 / 20181117220111 / files
nightly mac
77223bb2fac2 / 65.0a1 / 20181117220111 / files
nightly win32
77223bb2fac2 / 65.0a1 / 20181117220111 / files
nightly win64
77223bb2fac2 / 65.0a1 / 20181117220111 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
--- a/browser/base/content/browser-contentblocking.js
+++ b/browser/base/content/browser-contentblocking.js
@@ -3,32 +3,46 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var TrackingProtection = {
   reportBreakageLabel: "trackingprotection",
   telemetryIdentifier: "tp",
   PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled",
   PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.enabled",
   PREF_UI_ENABLED: "browser.contentblocking.trackingprotection.control-center.ui.enabled",
+  PREF_TRACKING_TABLE: "urlclassifier.trackingTable",
+  PREF_TRACKING_ANNOTATION_TABLE: "urlclassifier.trackingAnnotationTable",
   enabledGlobally: false,
   enabledInPrivateWindows: false,
 
   get categoryItem() {
     delete this.categoryItem;
     return this.categoryItem =
       document.getElementById("identity-popup-content-blocking-category-tracking-protection");
   },
 
+  get subViewList() {
+    delete this.subViewList;
+    return this.subViewList = document.getElementById("identity-popup-trackersView-list");
+  },
+
+  get strictInfo() {
+    delete this.strictInfo;
+    return this.strictInfo = document.getElementById("identity-popup-trackersView-strict-info");
+  },
+
   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);
+    XPCOMUtils.defineLazyPreferenceGetter(this, "trackingTable", this.PREF_TRACKING_TABLE, false);
+    XPCOMUtils.defineLazyPreferenceGetter(this, "trackingAnnotationTable", this.PREF_TRACKING_ANNOTATION_TABLE, false);
   },
 
   uninit() {
     Services.prefs.removeObserver(this.PREF_ENABLED_GLOBALLY, this);
     Services.prefs.removeObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
   },
 
   observe() {
@@ -46,16 +60,96 @@ var TrackingProtection = {
       Services.prefs.getBoolPref(this.PREF_ENABLED_GLOBALLY);
     this.enabledInPrivateWindows =
       Services.prefs.getBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS);
   },
 
   isBlockerActivated(state) {
     return state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT;
   },
+
+  isAllowing(state) {
+    return state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT;
+  },
+
+  async updateSubView() {
+    let previousURI = gBrowser.currentURI.spec;
+    let previousWindow = gBrowser.selectedBrowser.innerWindowID;
+
+    let contentBlockingLogJSON = await gBrowser.selectedBrowser.getContentBlockingLog();
+    let contentBlockingLog = JSON.parse(contentBlockingLogJSON);
+
+    // Don't tell the user to turn on TP if they are already blocking trackers.
+    this.strictInfo.hidden = this.enabled;
+
+    let fragment = document.createDocumentFragment();
+    for (let [origin, actions] of Object.entries(contentBlockingLog)) {
+      let listItem = await this._createListItem(origin, actions);
+      if (listItem) {
+        fragment.appendChild(listItem);
+      }
+    }
+
+    // This might have taken a while. Only update the list if we're still on the same page.
+    if (previousURI == gBrowser.currentURI.spec &&
+        previousWindow == gBrowser.selectedBrowser.innerWindowID) {
+      this.subViewList.textContent = "";
+      this.subViewList.append(fragment);
+    }
+  },
+
+  // Given a URI from a source that was tracking-annotated, figure out
+  // if it's really on the tracking table or just on the annotation table.
+  _isOnTrackingTable(uri) {
+    if (this.trackingTable == this.trackingAnnotationTable) {
+      return true;
+    }
+    return new Promise(resolve => {
+      classifierService.asyncClassifyLocalWithTables(uri, this.trackingTable, [], [],
+        (code, list) => resolve(!!list));
+    });
+  },
+
+  async _createListItem(origin, actions) {
+    // Figure out if this list entry was actually detected by TP or something else.
+    let isDetected = false;
+    let isAllowed = false;
+    for (let [state] of actions) {
+      isAllowed = isAllowed || this.isAllowing(state);
+      isDetected = isDetected || isAllowed || this.isBlockerActivated(state);
+    }
+
+    if (!isDetected) {
+      return null;
+    }
+
+    let uri = Services.io.newURI(origin);
+
+    // Because we might use different lists for annotation vs. blocking, we
+    // need to make sure that this is a tracker that we would actually have blocked
+    // before showing it to the user.
+    let isTracker = await this._isOnTrackingTable(uri);
+    if (!isTracker) {
+      return null;
+    }
+
+    let listItem = document.createXULElement("hbox");
+    listItem.className = "identity-popup-trackersView-list-item";
+    listItem.classList.toggle("allowed", isAllowed);
+
+    let image = document.createXULElement("image");
+    listItem.append(image);
+
+    let label = document.createXULElement("label");
+    label.value = uri.host;
+    label.setAttribute("crop", "end");
+    listItem.append(label);
+
+    return listItem;
+  },
 };
 
 var ThirdPartyCookies = {
   telemetryIdentifier: "cr",
   PREF_ENABLED: "network.cookie.cookieBehavior",
   PREF_REPORT_BREAKAGE_ENABLED: "browser.contentblocking.rejecttrackers.reportBreakage.enabled",
   PREF_ENABLED_VALUES: [
     // These values match the ones exposed under the Content Blocking section
@@ -142,16 +236,21 @@ var ContentBlocking = {
     return this.PREF_INTRO_COUNT_CB;
   },
 
   get appMenuLabel() {
     delete this.appMenuLabel;
     return this.appMenuLabel = document.getElementById("appMenu-tp-label");
   },
 
+  get identityPopup() {
+    delete this.identityPopup;
+    return this.identityPopup = document.getElementById("identity-popup");
+  },
+
   strings: {
     get appMenuTitle() {
       delete this.appMenuTitle;
       return this.appMenuTitle =
         gNavigatorBundle.getString("contentBlocking.title");
     },
 
     get appMenuTooltip() {
@@ -233,30 +332,30 @@ var ContentBlocking = {
         blocker.uninit();
       }
     }
 
     Services.prefs.removeObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled);
   },
 
   hideIdentityPopupAndReload() {
-    document.getElementById("identity-popup").hidePopup();
+    this.identityPopup.hidePopup();
     BrowserReload();
   },
 
   openPreferences(origin) {
     openPreferences("privacy-trackingprotection", { origin });
   },
 
   backToMainView() {
     this.identityPopupMultiView.goBack();
   },
 
   submitBreakageReport() {
-    document.getElementById("identity-popup").hidePopup();
+    this.identityPopup.hidePopup();
 
     let reportEndpoint = Services.prefs.getStringPref(this.PREF_REPORT_BREAKAGE_URL);
     if (!reportEndpoint) {
       return;
     }
 
     let formData = new FormData();
     formData.set("title", this.reportURI.host);
@@ -309,16 +408,21 @@ var ContentBlocking = {
     // Save this URI to make sure that the user really only submits the location
     // they see in the report breakage dialog.
     this.reportURI = gBrowser.currentURI;
     let urlWithoutQuery = this.reportURI.asciiSpec.replace("?" + this.reportURI.query, "");
     this.reportBreakageURL.textContent = urlWithoutQuery;
     this.identityPopupMultiView.showSubView("identity-popup-breakageReportView");
   },
 
+  async showTrackersSubview() {
+    await TrackingProtection.updateSubView();
+    this.identityPopupMultiView.showSubView("identity-popup-trackersView");
+  },
+
   shieldHistogramAdd(value) {
     if (PrivateBrowsingUtils.isWindowPrivate(window)) {
       return;
     }
     Services.telemetry.getHistogramById("TRACKING_PROTECTION_SHIELD").add(value);
   },
 
   onSecurityChange(oldState, state, webProgress, isSimulated,
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -138,16 +138,17 @@ XPCOMUtils.defineLazyScriptGetter(this, 
 if (AppConstants.NIGHTLY_BUILD) {
   XPCOMUtils.defineLazyScriptGetter(this, "gWebRender",
                                     "chrome://browser/content/browser-webrender.js");
 }
 
 // lazy service getters
 
 XPCOMUtils.defineLazyServiceGetters(this, {
+  classifierService: ["@mozilla.org/url-classifier/dbservice;1", "nsIURIClassifier"],
   Favicons: ["@mozilla.org/browser/favicon-service;1", "nsIFaviconService"],
   gAboutNewTabService: ["@mozilla.org/browser/aboutnewtab-service;1", "nsIAboutNewTabService"],
   gDNSService: ["@mozilla.org/network/dns-service;1", "nsIDNSService"],
   gSerializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],
   Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"],
   WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
 });
 
--- a/browser/base/content/test/trackingUI/browser.ini
+++ b/browser/base/content/test/trackingUI/browser.ini
@@ -18,8 +18,9 @@ support-files =
   file_trackingUI_fetch.js
   file_trackingUI_fetch.js^headers^
 [browser_trackingUI_open_preferences.js]
 [browser_trackingUI_pbmode_exceptions.js]
 [browser_trackingUI_report_breakage.js]
 [browser_trackingUI_state.js]
 [browser_trackingUI_state_all_disabled.js]
 [browser_trackingUI_telemetry.js]
+[browser_trackingUI_trackers_subview.js]
--- a/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
@@ -54,19 +54,19 @@ function testTrackingPage(window) {
     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"),
+  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > #identity-popup-content-blocking-tracking-protection-label-allowed"),
+    "TP category item is not showing the allowed label");
+  ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > #identity-popup-content-blocking-tracking-protection-label-blocked"),
     "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");
 
@@ -79,19 +79,19 @@ function testTrackingPageUnblocked() {
   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"),
+  ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > #identity-popup-content-blocking-tracking-protection-label-allowed"),
+    "TP category item is showing the allowed label");
+  ok(hidden("#identity-popup-content-blocking-category-tracking-protection > #identity-popup-content-blocking-tracking-protection-label-blocked"),
     "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_state.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_state.js
@@ -129,30 +129,36 @@ function testTrackingPage(window) {
     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 = 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");
 
-  if (Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER) {
+  let cookiesBlocked = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
+  if (cookiesBlocked) {
+    let category = "#identity-popup-content-blocking-category-3rdpartycookies";
+    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");
+
     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 {
+    let category = "#identity-popup-content-blocking-category-tracking-protection";
+    is(hidden(category + " > #identity-popup-content-blocking-tracking-protection-label-allowed"), blockedByTP,
+      "Category item is" + (blockedByTP ? " not" : "") + " showing the allowed label");
+    is(!hidden(category + " > #identity-popup-content-blocking-tracking-protection-label-blocked"), blockedByTP,
+      "Category item is" + (blockedByTP ? "" : " not") + " set to blocked");
+
     ok(hidden("#identity-popup-content-blocking-category-label-trackers"),
       "Not showing trackers cookie restrictions label.");
     ok(!hidden("#identity-popup-content-blocking-category-label-default"),
       "Showing default cookie restrictions label.");
   }
 }
 
 function testTrackingPageUnblocked(blockedByTP, window) {
@@ -170,24 +176,32 @@ function testTrackingPageUnblocked(block
   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");
-  let 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");
+
+  let cookiesBlocked = Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
+  if (cookiesBlocked) {
+    let category = "#identity-popup-content-blocking-category-3rdpartycookies";
+    is(hidden(category + " > .identity-popup-content-blocking-category-add-blocking"), blockedByTP,
+      "Category item is" + (blockedByTP ? " not" : "") + " showing add blocking");
+    ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > #identity-popup-content-blocking-tracking-protection-label-allowed"),
+      "TP category item is showing the allowed label");
+  } else {
+    let category = "#identity-popup-content-blocking-category-tracking-protection";
+    // If there's an exception we always show the "Allowed" label.
+    ok(!hidden(category + " > #identity-popup-content-blocking-tracking-protection-label-allowed"),
+      "Category item is showing the allowed label");
+    ok(hidden(category + " > #identity-popup-content-blocking-tracking-protection-label-blocked"),
+      "Category item is not set to blocked");
+  }
 }
 
 async function testContentBlocking(tab) {
   info("Testing with Tracking Protection ENABLED.");
 
   info("Load a test page not containing tracking elements");
   await promiseTabLoadEvent(tab, BENIGN_PAGE);
   testBenignPage();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
@@ -0,0 +1,118 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
+
+const TP_PREF = "privacy.trackingprotection.enabled";
+
+add_task(async function setup() {
+  await UrlClassifierTestUtils.addTestTrackers();
+});
+
+function openIdentityPopup() {
+  let mainView = document.getElementById("identity-popup-mainView");
+  let viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
+  gIdentityHandler._identityBox.click();
+  return viewShown;
+}
+
+function waitForSecurityChange(blocked) {
+  return new Promise(resolve => {
+    let webProgressListener = {
+      onStateChange: () => {},
+      onStatusChange: () => {},
+      onLocationChange: () => {},
+      onSecurityChange: (webProgress, request, oldState, state) => {
+        if ((!blocked && state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) ||
+            (blocked && state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT)) {
+          gBrowser.removeProgressListener(webProgressListener);
+          resolve();
+        }
+      },
+      onProgressChange: () => {},
+      QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener]),
+    };
+
+    gBrowser.addProgressListener(webProgressListener);
+  });
+}
+
+async function assertSitesListed(blocked) {
+  await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function(browser) {
+    await openIdentityPopup();
+
+    let categoryItem =
+      document.getElementById("identity-popup-content-blocking-category-tracking-protection");
+    ok(BrowserTestUtils.is_visible(categoryItem), "TP category item is visible");
+    let trackersView = document.getElementById("identity-popup-trackersView");
+    let viewShown = BrowserTestUtils.waitForEvent(trackersView, "ViewShown");
+    categoryItem.click();
+    await viewShown;
+
+    ok(true, "Trackers view was shown");
+
+    let listItems = document.querySelectorAll(".identity-popup-trackersView-list-item");
+    is(listItems.length, 1, "We have 1 tracker in the list");
+
+    let strictInfo = document.getElementById("identity-popup-trackersView-strict-info");
+    is(BrowserTestUtils.is_hidden(strictInfo), Services.prefs.getBoolPref(TP_PREF),
+      "Strict info is hidden if TP is enabled.");
+
+    let mainView = document.getElementById("identity-popup-mainView");
+    viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
+    let backButton = trackersView.querySelector(".subviewbutton-back");
+    backButton.click();
+    await viewShown;
+
+    ok(true, "Main view was shown");
+
+    let change = waitForSecurityChange(blocked);
+
+    await ContentTask.spawn(browser, {}, function() {
+      content.postMessage("more-tracking", "*");
+    });
+
+    await change;
+
+    viewShown = BrowserTestUtils.waitForEvent(trackersView, "ViewShown");
+    categoryItem.click();
+    await viewShown;
+
+    ok(true, "Trackers view was shown");
+
+    listItems = Array.from(document.querySelectorAll(".identity-popup-trackersView-list-item"));
+    is(listItems.length, 2, "We have 2 trackers in the list");
+
+    let listItem = listItems.find(item => item.querySelector("label").value == "trackertest.org");
+    ok(listItem, "Has an item for trackertest.org");
+    ok(BrowserTestUtils.is_visible(listItem), "List item is visible");
+    is(listItem.classList.contains("allowed"), !blocked,
+      "Indicates whether the tracker was blocked or allowed");
+
+    listItem = listItems.find(item => item.querySelector("label").value == "itisatracker.org");
+    ok(listItem, "Has an item for itisatracker.org");
+    ok(BrowserTestUtils.is_visible(listItem), "List item is visible");
+    is(listItem.classList.contains("allowed"), !blocked,
+      "Indicates whether the tracker was blocked or allowed");
+  });
+}
+
+add_task(async function testTrackersSubView() {
+  Services.prefs.setBoolPref(TP_PREF, false);
+  await assertSitesListed(false);
+  Services.prefs.setBoolPref(TP_PREF, true);
+  await assertSitesListed(true);
+  let uri = Services.io.newURI("https://tracking.example.org");
+  Services.perms.add(uri, "trackingprotection", Services.perms.ALLOW_ACTION);
+  await assertSitesListed(false);
+  Services.perms.remove(uri, "trackingprotection");
+  await assertSitesListed(true);
+  Services.prefs.clearUserPref(TP_PREF);
+});
+
+add_task(function cleanup() {
+  Services.prefs.clearUserPref(TP_PREF);
+  UrlClassifierTestUtils.cleanupTestTrackers();
+});
--- a/browser/base/content/test/trackingUI/trackingAPI.js
+++ b/browser/base/content/test/trackingUI/trackingAPI.js
@@ -1,16 +1,22 @@
 onmessage = event => {
   switch (event.data) {
   case "tracking": {
       let ifr = document.createElement("iframe");
       ifr.src = "https://trackertest.org/";
       document.body.appendChild(ifr);
     }
     break;
+  case "more-tracking": {
+      let ifr = document.createElement("iframe");
+      ifr.src = "https://itisatracker.org/";
+      document.body.appendChild(ifr);
+    }
+    break;
   case "cookie": {
       let ifr = document.createElement("iframe");
       ifr.src = "https://trackertest.org/browser/browser/base/content/test/trackingUI/cookieServer.sjs";
       document.body.appendChild(ifr);
     }
     break;
   }
 };
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -77,25 +77,26 @@
           </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>
 
           <vbox id="identity-popup-content-blocking-category-list">
-            <hbox id="identity-popup-content-blocking-category-tracking-protection"
-                  class="identity-popup-content-blocking-category" align="center" role="group">
+            <toolbarbutton id="identity-popup-content-blocking-category-tracking-protection"
+                  onclick="ContentBlocking.showTrackersSubview()"
+                  class="identity-popup-content-blocking-category" align="center">
               <image class="identity-popup-content-blocking-category-icon tracking-protection-icon"/>
               <label flex="1" class="identity-popup-content-blocking-category-label">&contentBlocking.trackingProtection3.label;</label>
-              <label flex="1" class="identity-popup-content-blocking-category-state-label">&contentBlocking.trackingProtection.blocking.label;</label>
-              <label flex="1" class="identity-popup-content-blocking-category-add-blocking text-link"
-                     id="identity-popup-tracking-protection-add-blocking"
-                     onclick="ContentBlocking.openPreferences('identityPopup-CB-tracking-protection'); gIdentityHandler.recordClick('tp_add_blocking');">&contentBlocking.trackingProtection.add.label;</label>
-            </hbox>
+              <label flex="1" id="identity-popup-content-blocking-tracking-protection-label-allowed"
+                     class="identity-popup-content-blocking-category-state-label">&contentBlocking.trackingProtection.allowed.label;</label>
+              <label flex="1" id="identity-popup-content-blocking-tracking-protection-label-blocked"
+                     class="identity-popup-content-blocking-category-state-label">&contentBlocking.trackingProtection.blocked.label;</label>
+            </toolbarbutton>
             <hbox id="identity-popup-content-blocking-category-3rdpartycookies"
                   class="identity-popup-content-blocking-category" align="center" role="group">
               <image class="identity-popup-content-blocking-category-icon thirdpartycookies-icon"/>
               <label flex="1" id="identity-popup-content-blocking-category-label-default"
                      class="identity-popup-content-blocking-category-label">&contentBlocking.3rdPartyCookies.label;</label>
               <label flex="1" id="identity-popup-content-blocking-category-label-trackers"
                      hidden="true" class="identity-popup-content-blocking-category-label">&contentBlocking.3rdPartyCookies.trackers.label;</label>
               <label flex="1" class="identity-popup-content-blocking-category-state-label">&contentBlocking.3rdPartyCookies.blocking.label;</label>
@@ -244,16 +245,35 @@
         <!-- More Security Information -->
         <button id="identity-popup-more-info"
                 label="&identity.moreInfoLinkText2;"
                 oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
       </vbox>
 
     </panelview>
 
+    <!-- Trackers SubView -->
+    <panelview id="identity-popup-trackersView"
+               role="document"
+               title="&contentBlocking.trackersView.label;"
+               descriptionheightworkaround="true">
+        <vbox id="identity-popup-trackersView-list">
+        </vbox>
+        <hbox id="identity-popup-trackersView-strict-info">
+          <image/>
+          <label>&contentBlocking.trackersView.strictInfo.label;</label>
+        </hbox>
+        <vbox class="identity-popup-footer">
+          <button id="identity-popup-trackersView-settings-button"
+                  label="&contentBlocking.manageSettings.label;"
+                  accesskey="&contentBlocking.manageSettings.accesskey;"
+                  oncommand="ContentBlocking.openPreferences();"/>
+        </vbox>
+    </panelview>
+
     <!-- Report Breakage SubView -->
     <panelview id="identity-popup-breakageReportView"
                title="&contentBlocking.breakageReportView.label;"
                descriptionheightworkaround="true">
         <vbox id="identity-popup-breakageReportView-heading">
           <description>&contentBlocking.breakageReportView2.description;</description>
           <label id="identity-popup-breakageReportView-learn-more"
                  class="text-link">&contentBlocking.breakageReportView.learnMore;</label>
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -965,34 +965,29 @@ you can use these alternative items. Oth
 
 <!ENTITY contentBlocking.title "Content Blocking">
 <!ENTITY contentBlocking.detected "Blockable content detected on this site.">
 <!ENTITY contentBlocking.notDetected "No blockable content detected on this page.">
 <!ENTITY contentBlocking.disabled.label "Disabled">
 <!ENTITY contentBlocking.disabled.tooltip "You have disabled Content Blocking.">
 <!ENTITY contentBlocking.exception.tooltip "You have disabled Content Blocking for this site.">
 
-<!ENTITY contentBlocking.trackingProtection2.label "All Detected Trackers">
 <!ENTITY contentBlocking.trackingProtection3.label "Trackers">
+<!-- LOCALIZATION NOTE (contentBlocking.trackingProtection.allowed.label):
+     This label signals that this type of content blocking is turned
+     OFF and is not blocking tracker content, so this is not
+     a positive thing. It forms the end of the (imaginary) sentence
+     "Trackers [are] Allowed"-->
+<!ENTITY contentBlocking.trackingProtection.allowed.label "Allowed">
 <!-- LOCALIZATION NOTE (contentBlocking.trackingProtection.blocked.label):
      This label signals that this type of content blocking is turned
      ON and is successfully blocking tracker content, so this is
      a positive thing. It forms the end of the (imaginary) sentence
      "Trackers [are] Blocked"-->
 <!ENTITY contentBlocking.trackingProtection.blocked.label "Blocked">
-<!-- LOCALIZATION NOTE (contentBlocking.tranckingProtection.blocking.label):
-     This label signals that this type of content blocking is turned
-     ON, so this is a positive thing. It forms the verb in the (imaginary) sentence
-     "Firefox is blocking Trackers"-->
-<!ENTITY contentBlocking.trackingProtection.blocking.label "Blocking">
-<!-- LOCALIZATION NOTE (contentBlocking.trackingProtection.add.label):
-     This is displayed as a link to preferences, where the user can add
-     this specific type of content blocking. When this text is shown
-     the type of content blocking is currently not enabled. -->
-<!ENTITY contentBlocking.trackingProtection.add.label "Add Blocking…">
 
 <!ENTITY contentBlocking.3rdPartyCookies.label "Third-Party Cookies">
 <!ENTITY contentBlocking.3rdPartyCookies.trackers.label "Tracking Cookies">
 <!-- LOCALIZATION NOTE (contentBlocking.3rdPartyCookies.blocked.label):
      This label signals that this type of content blocking is turned
      ON and is successfully blocking third-party cookies, so this is
      a positive thing. It forms the end of the (imaginary) sentence
      "Third-Party Cookies [are] Blocked"-->
@@ -1003,16 +998,22 @@ you can use these alternative items. Oth
      "Firefox is blocking Third-Party Cookies"-->
 <!ENTITY contentBlocking.3rdPartyCookies.blocking.label "Blocking">
 <!-- LOCALIZATION NOTE (contentBlocking.3rdPartyCookies.add.label):
      This is displayed as a link to preferences, where the user can add
      this specific type of content blocking. When this text is shown
      the type of content blocking is currently not enabled. -->
 <!ENTITY contentBlocking.3rdPartyCookies.add.label "Add Blocking…">
 
+<!ENTITY contentBlocking.manageSettings.label "Manage Content Blocking">
+<!ENTITY contentBlocking.manageSettings.accesskey "M">
+
+<!ENTITY contentBlocking.trackersView.label "Trackers">
+<!ENTITY contentBlocking.trackersView.strictInfo.label "To block all trackers, set content blocking to “Strict”.">
+
 <!ENTITY contentBlocking.openBreakageReportView2.label "Report a problem">
 <!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">
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/controlcenter/info.svg
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="context-fill" fill-rule="evenodd" d="M8 1a7 7 0 1 1-7 7 7 7 0 0 1 7-7zm0 3a1 1 0 1 1-1 1 1 1 0 0 1 1-1zm0 3a1 1 0 0 1 1 1v3a1 1 0 0 1-2 0V8a1 1 0 0 1 1-1z"></path></svg>
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -4,16 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 %endif
 
 /* Hide all conditional elements by default. */
 :-moz-any([when-connection],[when-mixedcontent],[when-ciphers],[when-loginforms]) {
   display: none;
 }
 
+#identity-popup {
+  --identity-popup-width: 33rem;
+}
+
 /* This is used by screenshots tests to hide intermittently different
  * identity popup shadows (see bug 1425253). */
 #identity-popup.no-shadow {
   -moz-window-shadow: none;
 }
 
 /* Show the right elements for the right connection states. */
 #identity-popup[connection=not-secure] [when-connection~=not-secure],
@@ -63,18 +67,18 @@
   padding: 0;
   /* Set default fill for icons in the identity popup.
      Individual icons can override this. */
   fill: currentColor;
   fill-opacity: .6;
 }
 
 #identity-popup-mainView {
-  min-width: 33em;
-  max-width: 33em;
+  min-width: var(--identity-popup-width);
+  max-width: var(--identity-popup-width);
 }
 
 .identity-popup-section {
   border-top: 1px solid var(--panel-separator-color);
 }
 
 .identity-popup-security-content,
 #identity-popup-permissions-content,
@@ -140,17 +144,22 @@
 }
 
 .identity-popup-preferences-button > .toolbarbutton-text {
   display: none;
 }
 
 /* CONTENT */
 
+.identity-popup-footer,
+.tracking-protection-button,
+#identity-popup-trackersView-strict-info > label,
+.identity-popup-trackersView-list-item > label,
 #identity-popup-mainView-panel-header > label,
+#identity-popup-trackersView > .panel-header,
 #identity-popup-securityView > .panel-header,
 #identity-popup-breakageReportView > .panel-header,
 #identity-popup-content-blocking-report-breakage,
 #identity-popup-content-blocking-disabled-label,
 .identity-popup-content-blocking-category-label,
 .identity-popup-content-blocking-category-state-label,
 .identity-popup-content-blocking-category-add-blocking,
 .identity-popup-permission-label,
@@ -173,17 +182,17 @@
 
 #identity-popup-mainView-panel-header-span {
   display: inline-block;
   font-weight: 600;
   text-align: center;
   overflow-wrap: break-word;
   /* This is needed for the overflow-wrap to work correctly.
    * 33em is the panel width, panel-header has 1em padding on each side. */
-  max-width: calc(33rem - 2em);
+  max-width: calc(var(--identity-popup-width) - 2em);
 }
 
 #identity-popup-permissions-content > description,
 #identity-popup-content-blocking-content > description {
   color: var(--panel-disabled-color);
 }
 
 /* This element needs the pre-wrap because we add newlines to it in the code. */
@@ -196,17 +205,17 @@
   font-size: 150%;
 }
 
 #identity-popup-host {
   overflow-wrap: break-word;
   /* This is needed for the overflow-wrap to work correctly.
    * 1em + 2em + 24px is .identity-popup-security-content padding
    * 33em is the panel width */
-  max-width: calc(33rem - 3rem - 24px);
+  max-width: calc(var(--identity-popup-width) - 3rem - 24px);
 }
 
 .identity-popup-warning-gray {
   padding-inline-start: 24px;
   background: url(chrome://browser/skin/controlcenter/warning.svg) no-repeat 0 50%;
   fill: #808080;
   stroke: #fff;
   -moz-context-properties: fill, stroke;
@@ -377,16 +386,103 @@ 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");
 }
 
+#identity-popup-content-blocking-category-tracking-protection {
+  /* Overwrite toolbarbutton styles */
+  margin: 0;
+  padding-inline-start: 0;
+}
+
+#identity-popup-content-blocking-category-tracking-protection:-moz-focusring,
+#identity-popup-content-blocking-category-tracking-protection:hover {
+  border-radius: 2px;
+  background-color: var(--arrowpanel-dimmed-further);
+}
+
+#identity-popup-content-blocking-category-tracking-protection:hover:active {
+  background-color: var(--arrowpanel-dimmed-even-further);
+}
+
+#identity-popup-content-blocking-category-tracking-protection::after {
+  content: url(chrome://browser/skin/back-12.svg);
+  -moz-context-properties: fill, fill-opacity;
+  transform: scaleX(-1) translateY(1px);
+  float: right;
+}
+
+#identity-popup-content-blocking-category-tracking-protection:-moz-locale-dir(rtl)::after {
+  transform: scaleX(1) translateY(1px);
+}
+
+/* This subview could get filled with a lot of trackers, set a maximum size
+ * and allow it to scroll vertically.*/
+#identity-popup-trackersView {
+  max-height: 600px;
+}
+
+#identity-popup-trackersView-list {
+  padding: 5px 20px;
+  -moz-box-flex: 1;
+  overflow: scroll;
+}
+
+.identity-popup-trackersView-list-item {
+  margin: 5px 0;
+  overflow: hidden;
+}
+
+.identity-popup-trackersView-list-item > label {
+  /* Limit to full width - container padding - icon width - icon margin */
+  max-width: calc(var(--identity-popup-width) - 40px - 16px - 10px);
+}
+
+.identity-popup-trackersView-list-item > image {
+  list-style-image: url(chrome://browser/skin/controlcenter/trackers-disabled.svg);
+  margin-inline-end: 10px;
+  -moz-context-properties: fill, fill-opacity;
+}
+
+.identity-popup-trackersView-list-item.allowed > image {
+  list-style-image: url(chrome://browser/skin/controlcenter/trackers.svg);
+}
+
+#identity-popup-trackersView-strict-info {
+  min-height: 40px;
+  /* Limit to full width - margin */
+  max-width: calc(var(--identity-popup-width) - 12px);
+  min-width: calc(var(--identity-popup-width) - 12px);
+  background-color: #45a1ff80;
+  margin: 6px;
+  text-align: center;
+  -moz-box-align: center;
+  -moz-box-pack: center;
+  padding: 5px 15px;
+  border-radius: 3px;
+  color: #002275;
+}
+
+#identity-popup-trackersView-strict-info > image {
+  list-style-image: url(chrome://browser/skin/controlcenter/info.svg);
+  -moz-context-properties: fill;
+  fill: currentColor;
+  margin-inline-end: 10px;
+}
+
+#identity-popup-trackersView-strict-info > label {
+  overflow-wrap: break-word;
+  /* Limit to full width - container margin - container padding - icon width - icon margin */
+  max-width: calc(var(--identity-popup-width) - 12px - 20px - 16px - 10px);
+}
+
 /* Disabled label */
 
 #identity-popup-content-blocking-disabled-label {
   padding: 2px 5px;
   border-radius: 3px;
   margin: 5px;
   display: none;
   color: #fff;
@@ -428,21 +524,30 @@ description#identity-popup-content-verif
 }
 
 /* Show the "detected"/"not detected" message depending on the content state. */
 #identity-popup-content-blocking-content:not([detected]) > #identity-popup-content-blocking-detected,
 #identity-popup-content-blocking-content[detected] > #identity-popup-content-blocking-not-detected {
   display: none;
 }
 
-#identity-popup-content-blocking-content[hasException] .identity-popup-content-blocking-category-state-label,
-.identity-popup-content-blocking-category:not(.blocked) .identity-popup-content-blocking-category-state-label {
+.identity-popup-content-blocking-category-state-label {
   display: none;
 }
 
+/* TODO: This will be cleaned up by bug 1501992 */
+/* Hide the state label unless we blocked something only for third party cookies */
+#identity-popup-content-blocking-content:not([hasException]) #identity-popup-content-blocking-category-3rdpartycookies.blocked .identity-popup-content-blocking-category-state-label,
+/* For trackers, either show a "blocked" or "allowed" label depending on the state. */
+#identity-popup-content-blocking-content:not([hasException]) #identity-popup-content-blocking-category-tracking-protection.blocked > #identity-popup-content-blocking-tracking-protection-label-blocked,
+#identity-popup-content-blocking-category-tracking-protection:not(.blocked) > #identity-popup-content-blocking-tracking-protection-label-allowed,
+#identity-popup-content-blocking-content[hasException] #identity-popup-content-blocking-tracking-protection-label-allowed {
+  display: -moz-box;
+}
+
 .identity-popup-content-blocking-category.blocked .identity-popup-content-blocking-category-add-blocking {
   display: none;
 }
 
 .tracking-protection-icon {
   list-style-image: url(chrome://browser/skin/controlcenter/trackers.svg);
 }
 
@@ -463,16 +568,17 @@ description#identity-popup-content-verif
 .tracking-protection-button {
   list-style-image: url(chrome://browser/skin/tracking-protection.svg);
   -moz-appearance: none;
   margin: 1em 0 0;
   display: none;
   height: 32px;
   background-color: var(--arrowpanel-dimmed);
   color: inherit;
+  margin-inline-end: 8px;
 }
 
 .tracking-protection-button:hover {
   background-color: var(--arrowpanel-dimmed-further);
 }
 
 .tracking-protection-button:hover:active {
   background-color: var(--arrowpanel-dimmed-even-further);
@@ -546,32 +652,41 @@ description#identity-popup-content-verif
   min-height: 24px;
 }
 
 #identity-popup-content-blocking-category-list,
 #identity-popup-permission-list {
   /* Offset the padding set on #identity-popup-permissions-content so that it
      shows up just below the section. The permission icons are 16px wide and
      should be right aligned with the section icon. */
-  margin-inline-start: calc(-1em - 16px);
+  margin-inline-start: calc(-1em - 24px);
 }
 
 .identity-popup-content-blocking-category,
 .identity-popup-permission-item {
   min-height: 24px;
 }
 
+.identity-popup-content-blocking-category {
+  padding-inline-end: 12px;
+}
+
+.identity-popup-permission-item {
+  padding-inline-end: 8px;
+}
+
 #identity-popup-permission-list:not(:empty) {
   margin-top: 5px;
 }
 
 .identity-popup-content-blocking-category-icon,
 .identity-popup-permission-icon {
   width: 16px;
   height: 16px;
+  margin-inline-start: 12px;
 }
 
 .identity-popup-permission-icon.in-use {
   -moz-context-properties: fill;
   fill: rgb(224, 41, 29);
   animation: 1.5s ease in-use-blink infinite;
 }
 
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -23,16 +23,17 @@
   skin/classic/browser/addons/addon-install-installed.svg      (../shared/addons/addon-install-installed.svg)
   skin/classic/browser/addons/addon-install-warning.svg        (../shared/addons/addon-install-warning.svg)
   skin/classic/browser/controlcenter/3rdpartycookies.svg       (../shared/controlcenter/3rdpartycookies.svg)
   skin/classic/browser/controlcenter/3rdpartycookies-disabled.svg (../shared/controlcenter/3rdpartycookies-disabled.svg)
   skin/classic/browser/controlcenter/conn-not-secure.svg       (../shared/controlcenter/conn-not-secure.svg)
   skin/classic/browser/controlcenter/connection.svg            (../shared/controlcenter/connection.svg)
   skin/classic/browser/controlcenter/mcb-disabled.svg          (../shared/controlcenter/mcb-disabled.svg)
   skin/classic/browser/controlcenter/extension.svg             (../shared/controlcenter/extension.svg)
+  skin/classic/browser/controlcenter/info.svg                  (../shared/controlcenter/info.svg)
   skin/classic/browser/controlcenter/permissions.svg           (../shared/controlcenter/permissions.svg)
   skin/classic/browser/controlcenter/trackers.svg              (../shared/controlcenter/trackers.svg)
   skin/classic/browser/controlcenter/trackers-disabled.svg     (../shared/controlcenter/trackers-disabled.svg)
   skin/classic/browser/controlcenter/tracking-protection.svg   (../shared/controlcenter/tracking-protection.svg)
   skin/classic/browser/controlcenter/warning.svg               (../shared/controlcenter/warning.svg)
   skin/classic/browser/customizableui/empty-overflow-panel.png     (../shared/customizableui/empty-overflow-panel.png)
   skin/classic/browser/customizableui/empty-overflow-panel@2x.png  (../shared/customizableui/empty-overflow-panel@2x.png)
   skin/classic/browser/customizableui/density-compact.svg      (../shared/customizableui/density-compact.svg)
index 4c453a7a9c928a97ab4ee4350298d709927494ce..cdbda27802a0b77d2d09e78becd64ffa26529d6c
GIT binary patch
literal 229376
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
z_ML~$-;J-wzF+2UMjowoL3zoVO}9+0o%0-Qyzl(^BOk4(!$-Xh)I2<?V;w0y?ry^j
z!=p21g{w0ptVUM0Q8SX?ZDw@5K1*-(oH6_Sp>uSv(WQe~L$^Omd>|LO=w3Pg0XdGl
z)={Obyc$ni-0HXQXtn;>vSFv`K2xc*sbh5Y20pk*Oxk$cq~Jub@yUBbbJra^CMUyO
zu&CH%t(S9IyaDN<;hh=b8ms3Tgn1a}((cTh`^hu-?SrQMPZ*R4o#_$L>*_{s)VQ<r
z?0nkt(3W?Gm8o1~HSRsUYe8_H!jAFW6ZkVH=MM_qG0{1HfxpqfS8V%<(l0H~NDkS(
zo#<AwLjiyErPRyjn+wphulFO?Pn{m!Mt@m;J1n_NF}y!{PkHxv*Lml7$9eU<oxF{_
zYThDV8E+~tpErRwo|njr=8fPD;ra9W@|<|qJUmZ}r^u7wzURK=KH@fWFL6(C4{`T!
zw{X|+7Y6_U0000000000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000002szfKw_j`iGG?`kPXY`WKGAxLc8
zvd>(QSYO386D4v?1&OuzyC$N<9b-XaRgf57l)xGZ5-XZ_8;TOU3<Qa)loEYWVyd1X
zu~a8TSCpXX2ojYW^R-2ZJS{<DAz4gQl)!2T5)00>tBVq^)C7sSZ*HiH64zA(iL!oP
z%A$m)k{~g&EKO0A;3x<Z(-rFFMTz}#f<(!wzOtf39~nVn3O+zul<=1lBqpcaloTay
zNC*-I@;c(8gf>o)$Ui?+ObRD1!%u|B@_X2lMZ~bYS$$c=^!)S$b`G1wBC!I}`=x7S
zY|O|{6X#rHA7anvP2(AG*Kj>@4(CK<X-!x@!8vn(=Fp7m87k?OY0J_G918m->nSTI
zn~_!2+s6z50000000000000000000000000000000000000000000000000000000
z0000000000000000000000000000000O(!fI1JVjomij~b3I%iETTbBLsTSj5#l&`
z*$8?vosmw*`}vstMV{$+@mw+%Ng`Mw7J^JQqv4d4R0fm8%*6Xqm~3i1HIBrl;C(pk
zL<W<}&Ln6fnrKN`HKiep2~--5gda{}v8nU~f*E3h=E$k(g)$lOR2l_8kV7R?$oQeD
zY-$R10*Os!&`o~(8jb&={rJDgGqS@)VG)bZE5XU@`Ow%DCLP_l;Y<#T&0o)#jWqn3
z!Un&+5A=Wg8ufmrLv(+pu+DF9i}r6{qm~tJI2JJ>;1NS%hiI`Vw0L_KHGxhcJ5Vx6
zDXBDyLmVST^G6G6{Kb*3{ug;_zrF3MzkQ7=KXdpg|4d<}-`*C*-@ZnL-@Zoq-@Zn<
z-@ZoK-@ZnfT(Wq6Fc!(ZMvy~f(DIUMViDn=pGd2T`S}nu5q0#5l$yd228YfjQR(;*
zR7yI*6fqXATle$2?ePI4@MKCXCjrmqZw5b<5DXAK;by3ZQ{p)2Hsb^62~;|T!bG={
zh`0z_YR|7J+H|}Xe=X=)mCj(Y6Em&(i*clrQYc=OG<$Th_HiVF9bzLXV^a`V(4l~p
z!D<@BC6bsl5}QQ#W(ybcbsUubf6+>*-+uH+{`NIW{Ps19|MoTFe)}55Qu%9?`K^(T
ze>Y>9m4)FQ<1OQj=N52>agm&7IeT+v<uG&nb9A#$XOGU-&w7wmmo+OVo$Jb5nROt?
zC}&>Qyqut%23}g$W9~@aschq%_U!Z7<G53@rex*w7Y6_U00000000000000000000
z00000000000000000000000000000000000000000000000000000000000000000
z000000Km_Z!l`1HV<Ig@KP^N*&BbvTteFKa6pP>qhKRo4?|{o|i2g=Bh5Yqjnm0wu
znwa8(v4{ad577~pRb?fT2o%cK1&z^ycn4ez7O^5&AZEgX245CxPsvE7GP^F^2(4r2
zhGSw80>Kfn7uK<$(&K0xGR2<7i6t{qNK`t@A(cv}Q|Sp`S2jQ^>;LvYpst6mR@YxV
zR~CzS5&9w?!i{!{C6OI^-f(+zCY_W*jr+O*I_Q$L&2WRUh#^5A(G@O8t($(*LQ85|
z;f7-o69OJF6qeLtQE2h@ENTM1YiSL%w7MRy4;IlNs39uC(y|fsWI7|Aj`#CXLkp;y
z<3g~A5y1e_6BbbC?^7pNV%NQ@f)-V_!$n~ci_iUolh^a1u_;VC+ONZfd$+THmCzcB
zeQ+6A#D(C5Ai^5fv77`Kg0lzW;gCVMw@=I<CB-IE5}ZgAoJlmntfUMQEtO15RY2>@
z>*GAJh$cZDQ5Dvg`)Zry&=RuW9ck(5=?<|ZdNKhmgAqO>+b3``(dRN~9qC-Mcs~C?
z&b>yELuAlul4@cR;h&#KtBLvf5Ht~W^of+3!Vm`k;N|Z`{0J%~onVR>3lAIJ&xegY
zK41i%OyRc-&*mRN{Eq$HnR06C;gmQI+8y`+dIFVBp)k<{jEJ}h4^n%6P0>+@w-TKq
z=?o@2G1HpA7)So0Lh+)c*`tfKk0TN65F1Gun}WcC4h5_XR?{FZk;J5t*d)3)Tey&~
zcbOF0RLSplndktt@8(RBKx>E_;|5?6J%SFRC9I)5gb|lW6|^jlMy1f%IJB4;f{T|y
zYzfwgrLZaZpp+DT1L<s9Cf=XQ5}ob*W}^=_zXxRbfyk1pj^R1;hH$s?Ht}+JbGc2t
z`@A#UWxNFLeQq#MgImD;$aUey^KSBv@>cVv@i@F_UI5RQr@(#9y~#b!UB@lwa=GKU
zzFa%58CRdbH~;_u00000000000000000000000000000000000000000000000000
z0000000000000000000000000000000000000000008)(Aca%KF2_V#ihf#%ewvGZ
znknE6u^hVSZ^@gA=9;MCY_P0E5+RyGC-WcZAD1^4<>9q(PMtMKbTTC)mCB@$jYRo|
z>Nq<ri%nuv<3g!)I+dQ_OClSHGWBI}n%L9?MjS~`G)Gqh=YS<=(n%>_m)8;HYRlnt
zv7!}diRNi4;_z4&g%;1ECeSHl4bg0MbT)^cOlPFiqvJ?wqS>nG^7&11awUG%7!^^j
zvI@=uOQNwUOgf1_VKCTAq8vpuCzg}oLU8s#JmM%!wt^@}9_=!I8(0)(8igq*nk$Qz
zr?BEksT2~MO^Qn<$cS>JRdH5WN*a~UUqK3mOy#dgN|Yt3i9^0={6GeSEFsDkN7t0X
zh)blhDJ(WlG*?U;N0gzaq)_Snw$L)8$yAnTXUOvRw`I-(46lWEkXOws;wAHj@Emz6
z+?U+*-0j@?+$`=`Zhx*Z7ngIFr^%hj_0MVKJ>VVVt>vZihVfjue{!#IYq^WKv0MwT
zbk3uk&Ad|n;s5{u00000000000000000000000000000000000000000000000000
z0000000000000000000000000000000000000000007{>NE_#ZofW+3jJAUOs<Pxu
z)ruSD-0=#NXtG2zva@RY{V~V<S#34Xen4V#qU)NCwiajxF`;r#{R7<l_FNt8lhR`I
zYq<(B=HfUE)~u&$rf9B7Pr1fuF21K+BQ)2rr}Y}3x%xfT)kAZ2d#bC0=4$s;R}0P6
z>?v0R%~kIyR}IZo?I~9U%~kGctCY}O#h&Uapt<rr<;tPCvOVR>pt;gL?Q<zKSF)$N
V5@@b?Pq{cWS4<1%BGX;&{{d`Z_=x}j
index 06c967ea7e9f3a56b1e5e8736f55a4402a41534a..fbdfa8c914a76beef0a1447cb45696e254af6bec
GIT binary patch
literal 294912
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
z9`Cb!?oNF4rLf)Q(lU>{U%B1iGSif)?$C9tJgy$WJAsH`@FTCCH9R+Mgo&>BH2QP{
z+4ty$X=QhE{TPGy6RD6|hcK+f_8o)dubVFx`IPeVxtQ&6G*^7lH=Dend6Utg@&291
z3o>lEyq$gMlec}XTVB1qz(k)>s{eW$n&wlC`1X^J-@novZj;Z`qw7KLvfd-pd(+F|
zSjpCd|Nr!6CnDPR=zsT-8vp<R0RLA|Z@!VnOcBL=j#=D%2LJ#7000000000000000
z00000000000000000000000000000000000000000000000000000000000000000
z00000000000002|Ka7%;j9B?zqb%vx%I&H5B-=>IsFZKrc|^T=D{0IJqL{BSYn$%?
z00000000000000000000000000000000000000000000000000000000000000000
z0000000000000000000000000000000D%7?$ViEZNq;U#NJ)vPsAKwwNTaogqP1ci
zqa*)sX9EBL0000000000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000004mh=8&ZRRFYCs5|UyRq*i34wEP%v
zC(j^fv{*opqqC0}3gaCh?u+sE#(2AmqeD?%zMg1tCm%1YGud%{VoB_4DH=(tpL<d;
zkyu&$^8zIkiH4dKizM^U3)`5s8~Frz2W}pU>mUXlBE=)g{quTirrkz9;TTU(6qgv6
z)<G_3v}2GfS0FkdkZW^i4#_<~H=<!;wm>@t`C|gZxU{@oG2Upj|7H{^q@?UtUM8{4
zJuNr)*}RfVaPy=12L%L%`1l99g$ZpQM#3BAg;qfai~T&Tm=j7$R8p9NN;qCOer-E3
z6)_8klN-w46BUT^J`nipApiPFlKPQhorxvgr35AUe|<DgOSG4-k3Y&kj7tOUABb_m
zIH3a3TxvmqZazOVO6`(l`SrQc|MPSEM>r{7NyM*DXpgDCj|;{V&7~8BaYj3HnfL}`
zyfERYK#Y$!$>u#GO6Xlj9kWP88uO4SrYB}{^Bn*H0000000000000000000000000
z00000000000000000000000000000000000000000000000000000000000000000
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
index b79fb90c8518548dfb6fdf9d1c3a4a8ab8343058..01c1f53efb1b5068c0ca7282b5b6831f319d6c0c
GIT binary patch
literal 2448
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
Az5oCK
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -170,16 +170,17 @@ https://sub.sectest1.example.org:443
 #
 http://malware.example.com:80
 http://unwanted.example.com:80
 http://tracking.example.com:80
 http://not-tracking.example.com:80
 http://tracking.example.org:80
 http://another-tracking.example.net:80
 http://itisatracker.org:80
+https://itisatracker.org:443
 http://trackertest.org:80
 
 https://malware.example.com:443
 https://unwanted.example.com:443
 https://tracking.example.com:443
 https://not-tracking.example.com:443
 https://tracking.example.org:443
 https://another-tracking.example.net:443
--- a/js/src/builtin/intl/CommonFunctions.js
+++ b/js/src/builtin/intl/CommonFunctions.js
@@ -1,30 +1,41 @@
 /* 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/. */
 
 /* Portions Copyright Norbert Lindenberg 2011-2012. */
 
+#ifdef DEBUG
+#define assertIsValidAndCanonicalLanguageTag(locale, desc) \
+    do { \
+        let localeObj = parseLanguageTag(locale); \
+        assert(localeObj !== null, \
+               `${desc} is a structurally valid language tag`); \
+        assert(CanonicalizeLanguageTagFromObject(localeObj) === locale, \
+               `${desc} is a canonicalized language tag`); \
+    } while (false)
+#else
+#define assertIsValidAndCanonicalLanguageTag(locale, desc) ; // Elided assertion.
+#endif
+
 /**
  * Returns the start index of a "Unicode locale extension sequence", which the
  * specification defines as: "any substring of a language tag that starts with
  * a separator '-' and the singleton 'u' and includes the maximum sequence of
  * following non-singleton subtags and their preceding '-' separators."
  *
  * Alternatively, this may be defined as: the components of a language tag that
  * match the extension production in RFC 5646, where the singleton component is
  * "u".
  *
  * Spec: ECMAScript Internationalization API Specification, 6.2.1.
  */
 function startOfUnicodeExtensions(locale) {
     assert(typeof locale === "string", "locale is a string");
-    assert(IsStructurallyValidLanguageTag(locale), "locale is a language tag");
-    assert(CanonicalizeLanguageTag(locale) === locale, "locale is a canonicalized language tag");
 
     #define HYPHEN 0x2D
     assert(std_String_fromCharCode(HYPHEN) === "-",
            "code unit constant should match the expected character");
 
     // A wholly-privateuse or grandfathered locale has no extension sequences.
     if (callFunction(std_String_charCodeAt, locale, 1) === HYPHEN) {
         assert(locale[0] === "x" || locale[0] === "i",
@@ -48,18 +59,16 @@ function startOfUnicodeExtensions(locale
     return start;
 }
 
 /**
  * Returns the end index of a Unicode locale extension sequence.
  */
 function endOfUnicodeExtensions(locale, start) {
     assert(typeof locale === "string", "locale is a string");
-    assert(IsStructurallyValidLanguageTag(locale), "locale is a language tag");
-    assert(CanonicalizeLanguageTag(locale) === locale, "locale is a canonicalized language tag");
     assert(0 <= start && start < locale.length, "start is an index into locale");
     assert(Substring(locale, start, 3) === "-u-", "start points to Unicode extension sequence");
 
     #define HYPHEN 0x2D
     assert(std_String_fromCharCode(HYPHEN) === "-",
            "code unit constant should match the expected character");
 
     // Search for the start of the next singleton or privateuse subtag.
@@ -86,38 +95,41 @@ function endOfUnicodeExtensions(locale, 
     // sequence extends until the end of the string.
     return locale.length;
 }
 
 /**
  * Removes Unicode locale extension sequences from the given language tag.
  */
 function removeUnicodeExtensions(locale) {
+    assertIsValidAndCanonicalLanguageTag(locale, "locale with possible Unicode extension");
+
     var start = startOfUnicodeExtensions(locale);
     if (start < 0)
         return locale;
 
     var end = endOfUnicodeExtensions(locale, start);
 
     var left = Substring(locale, 0, start);
     var right = Substring(locale, end, locale.length - end);
     var combined = left + right;
 
-    assert(IsStructurallyValidLanguageTag(combined),
-           "recombination produced an invalid language tag");
+    assertIsValidAndCanonicalLanguageTag(combined, "the recombined locale");
     assert(startOfUnicodeExtensions(combined) < 0,
            "recombination failed to remove all Unicode locale extension sequences");
 
     return combined;
 }
 
 /**
  * Returns Unicode locale extension sequences from the given language tag.
  */
 function getUnicodeExtensions(locale) {
+    assertIsValidAndCanonicalLanguageTag(locale, "locale with Unicode extension");
+
     var start = startOfUnicodeExtensions(locale);
     assert(start >= 0, "start of Unicode extension sequence not found");
     var end = endOfUnicodeExtensions(locale, start);
 
     return Substring(locale, start, end - start);
 }
 
 /* eslint-disable complexity */
@@ -787,18 +799,17 @@ function DefaultLocaleIgnoringAvailableL
         if (hasOwn(candidate, oldStyleLanguageTagMappings))
             candidate = oldStyleLanguageTagMappings[candidate];
     }
 
     // Cache the candidate locale until the runtime default locale changes.
     localeCandidateCache.candidateDefaultLocale = candidate;
     localeCandidateCache.runtimeDefaultLocale = runtimeDefaultLocale;
 
-    assert(IsStructurallyValidLanguageTag(candidate),
-           "the candidate must be structurally valid");
+    assertIsValidAndCanonicalLanguageTag(candidate, "the candidate locale");
     assert(startOfUnicodeExtensions(candidate) < 0,
            "the candidate must not contain a Unicode extension sequence");
 
     return candidate;
 }
 
 /**
  * Returns the BCP 47 language tag for the host environment's current locale.
@@ -825,20 +836,17 @@ function DefaultLocale() {
                                                         dateTimeFormatInternalProperties),
                                            candidate))
     {
         locale = candidate;
     } else {
         locale = lastDitchLocale();
     }
 
-    assert(IsStructurallyValidLanguageTag(locale),
-           "the computed default locale must be structurally valid");
-    assert(locale === CanonicalizeLanguageTag(locale),
-           "the computed default locale must be canonical");
+    assertIsValidAndCanonicalLanguageTag(locale, "the computed default locale");
     assert(startOfUnicodeExtensions(locale) < 0,
            "the computed default locale must not contain a Unicode extension sequence");
 
     localeCache.defaultLocale = locale;
     localeCache.runtimeDefaultLocale = runtimeDefaultLocale;
 
     return locale;
 }
@@ -919,18 +927,17 @@ function CanonicalizeLocaleList(locales)
         k++;
     }
 
     // Step 8.
     return seen;
 }
 
 function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLocale) {
-    assert(IsStructurallyValidLanguageTag(locale), "invalid BestAvailableLocale locale structure");
-    assert(locale === CanonicalizeLanguageTag(locale), "non-canonical BestAvailableLocale locale");
+    assertIsValidAndCanonicalLanguageTag(locale, "BestAvailableLocale locale");
     assert(startOfUnicodeExtensions(locale) < 0, "locale must contain no Unicode extensions");
 
     // In the spec, [[availableLocales]] is formally a list of all available
     // locales.  But in our implementation, it's an *incomplete* list, not
     // necessarily including the default locale (and all locales implied by it,
     // e.g. "de" implied by "de-CH"), if that locale isn't in every
     // [[availableLocales]] list (because that locale is supported through
     // fallback, e.g. "de-CH" supported through "de").
@@ -1244,22 +1251,19 @@ function ResolveLocale(availableLocales,
         if (privateIndex === -1) {
             foundLocale += supportedExtension;
         } else {
             var preExtension = callFunction(String_substring, foundLocale, 0, privateIndex);
             var postExtension = callFunction(String_substring, foundLocale, privateIndex);
             foundLocale = preExtension + supportedExtension + postExtension;
         }
 
-        // Step 9.d.
-        assert(IsStructurallyValidLanguageTag(foundLocale), "invalid locale after concatenation");
-
-        // Step 9.e (Not required in this implementation, because we don't
-        // canonicalize Unicode extension subtags).
-        assert(foundLocale === CanonicalizeLanguageTag(foundLocale), "same locale with extension");
+        // Steps 9.d-e (Step 9.e is not required in this implementation,
+        // because we don't canonicalize Unicode extension subtags).
+        assertIsValidAndCanonicalLanguageTag(foundLocale, "locale after concatenation");
     }
 
     // Step 10.
     result.locale = foundLocale;
 
     // Step 11.
     return result;
 }
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -2459,23 +2459,31 @@ RelocateArena(Arena* arena, SliceBudget&
         TenuredCell* dest = Forwarded(src);
         MOZ_ASSERT(src->isMarkedBlack() == dest->isMarkedBlack());
         MOZ_ASSERT(src->isMarkedGray() == dest->isMarkedGray());
     }
 #endif
 }
 
 static inline bool
+CanProtectArenas()
+{
+    // On some systems the page size is larger than the size of an arena so we
+    // can't change the mapping permissions per arena.
+    return SystemPageSize() <= ArenaSize;
+}
+
+static inline bool
 ShouldProtectRelocatedArenas(JS::gcreason::Reason reason)
 {
     // For zeal mode collections we don't release the relocated arenas
     // immediately. Instead we protect them and keep them around until the next
     // collection so we can catch any stray accesses to them.
 #ifdef DEBUG
-    return reason == JS::gcreason::DEBUG_GC;
+    return reason == JS::gcreason::DEBUG_GC && CanProtectArenas();
 #else
     return false;
 #endif
 }
 
 /*
  * Relocate all arenas identified by pickArenasToRelocate: for each arena,
  * relocate each cell within it, then add it to a list of relocated arenas.
@@ -2973,40 +2981,39 @@ GCRuntime::updateCellPointers(Zone* zone
 //   - Updating a typed object makes use of its type descriptor object
 //
 // This means we require at least three phases for update:
 //
 //  1) shapes
 //  2) typed object type descriptor objects
 //  3) all other objects
 //
-// Also, JSScripts and LazyScripts can have pointers to each other. Each can be
-// updated safely without requiring the referent to be up-to-date, but TSAN can
-// warn about data races when calling IsForwarded() on the new location of a
-// cell that is being updated in parallel. To avoid this, we update these in
-// separate phases.
+// Also, there can be data races calling IsForwarded() on the new location of a
+// cell that is being updated in parallel on another thread. This can be avoided
+// by updating some kinds of cells in different phases. This is done for JSScripts
+// and LazyScripts, and JSScripts and Scopes.
 //
 // Since we want to minimize the number of phases, arrange kinds into three
 // arbitrary phases.
 
 static const AllocKinds UpdatePhaseOne {
     AllocKind::SCRIPT,
     AllocKind::BASE_SHAPE,
     AllocKind::SHAPE,
     AllocKind::ACCESSOR_SHAPE,
     AllocKind::OBJECT_GROUP,
     AllocKind::STRING,
-    AllocKind::JITCODE,
-    AllocKind::SCOPE
+    AllocKind::JITCODE
 };
 
 // UpdatePhaseTwo is typed object descriptor objects.
 
 static const AllocKinds UpdatePhaseThree {
     AllocKind::LAZY_SCRIPT,
+    AllocKind::SCOPE,
     AllocKind::FUNCTION,
     AllocKind::FUNCTION_EXTENDED,
     AllocKind::OBJECT0,
     AllocKind::OBJECT0_BACKGROUND,
     AllocKind::OBJECT2,
     AllocKind::OBJECT2_BACKGROUND,
     AllocKind::OBJECT4,
     AllocKind::OBJECT4_BACKGROUND,