diff --git a/browser/base/content/browser-contentblocking.js b/browser/base/content/browser-contentblocking.js
new file mode 100644
index 000000000000..feecd6419fe2
--- /dev/null
+++ b/browser/base/content/browser-contentblocking.js
@@ -0,0 +1,1490 @@
+/* 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/. */
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "ContentBlockingAllowList",
+ "resource://gre/modules/ContentBlockingAllowList.jsm"
+);
+
+var Fingerprinting = {
+ PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
+ reportBreakageLabel: "fingerprinting",
+ telemetryIdentifier: "fp",
+
+ strings: {
+ get subViewBlocked() {
+ delete this.subViewBlocked;
+ return (this.subViewBlocked = gNavigatorBundle.getString(
+ "contentBlocking.fingerprintersView.blocked.label"
+ ));
+ },
+ },
+
+ init() {
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "enabled",
+ this.PREF_ENABLED,
+ false,
+ () => this.updateCategoryLabel()
+ );
+ this.updateCategoryLabel();
+ },
+
+ get categoryItem() {
+ delete this.categoryItem;
+ return (this.categoryItem = document.getElementById(
+ "identity-popup-content-blocking-category-fingerprinters"
+ ));
+ },
+
+ get categoryLabel() {
+ delete this.categoryLabel;
+ return (this.categoryLabel = document.getElementById(
+ "identity-popup-content-blocking-fingerprinters-state-label"
+ ));
+ },
+
+ get subViewList() {
+ delete this.subViewList;
+ return (this.subViewList = document.getElementById(
+ "identity-popup-fingerprintersView-list"
+ ));
+ },
+
+ updateCategoryLabel() {
+ let label;
+ if (this.enabled) {
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.fingerprinters.blocking.label"
+ : null;
+ } else {
+ label = ContentBlocking.showAllowedLabels
+ ? "contentBlocking.fingerprinters.allowed.label"
+ : null;
+ }
+ this.categoryLabel.textContent = label
+ ? gNavigatorBundle.getString(label)
+ : "";
+ },
+
+ isBlocking(state) {
+ return (
+ (state &
+ Ci.nsIWebProgressListener.STATE_BLOCKED_FINGERPRINTING_CONTENT) !=
+ 0
+ );
+ },
+
+ isAllowing(state) {
+ return (
+ this.enabled &&
+ (state & Ci.nsIWebProgressListener.STATE_LOADED_FINGERPRINTING_CONTENT) !=
+ 0
+ );
+ },
+
+ isDetected(state) {
+ return this.isBlocking(state) || this.isAllowing(state);
+ },
+
+ async updateSubView() {
+ let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
+ contentBlockingLog = JSON.parse(contentBlockingLog);
+
+ let fragment = document.createDocumentFragment();
+ for (let [origin, actions] of Object.entries(contentBlockingLog)) {
+ let listItem = this._createListItem(origin, actions);
+ if (listItem) {
+ fragment.appendChild(listItem);
+ }
+ }
+
+ this.subViewList.textContent = "";
+ this.subViewList.append(fragment);
+ },
+
+ _createListItem(origin, actions) {
+ let isAllowed = actions.some(([state]) => this.isAllowing(state));
+ let isDetected =
+ isAllowed || actions.some(([state]) => this.isBlocking(state));
+
+ if (!isDetected) {
+ return null;
+ }
+
+ let uri = Services.io.newURI(origin);
+
+ let listItem = document.createXULElement("hbox");
+ listItem.className = "identity-popup-content-blocking-list-item";
+ listItem.classList.toggle("allowed", isAllowed);
+ // Repeat the host in the tooltip in case it's too long
+ // and overflows in our panel.
+ listItem.tooltipText = uri.host;
+
+ let image = document.createXULElement("image");
+ image.className = "identity-popup-fingerprintersView-icon";
+ image.classList.toggle("allowed", isAllowed);
+ listItem.append(image);
+
+ let label = document.createXULElement("label");
+ label.value = uri.host;
+ label.className = "identity-popup-content-blocking-list-host-label";
+ label.setAttribute("crop", "end");
+ listItem.append(label);
+
+ if (!isAllowed) {
+ let stateLabel = document.createXULElement("label");
+ stateLabel.value = this.strings.subViewBlocked;
+ stateLabel.className = "identity-popup-content-blocking-list-state-label";
+ listItem.append(stateLabel);
+ }
+
+ return listItem;
+ },
+};
+
+var Cryptomining = {
+ PREF_ENABLED: "privacy.trackingprotection.cryptomining.enabled",
+ reportBreakageLabel: "cryptomining",
+ telemetryIdentifier: "cm",
+
+ strings: {
+ get subViewBlocked() {
+ delete this.subViewBlocked;
+ return (this.subViewBlocked = gNavigatorBundle.getString(
+ "contentBlocking.cryptominersView.blocked.label"
+ ));
+ },
+ },
+
+ init() {
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "enabled",
+ this.PREF_ENABLED,
+ false,
+ () => this.updateCategoryLabel()
+ );
+ this.updateCategoryLabel();
+ },
+
+ get categoryItem() {
+ delete this.categoryItem;
+ return (this.categoryItem = document.getElementById(
+ "identity-popup-content-blocking-category-cryptominers"
+ ));
+ },
+
+ get categoryLabel() {
+ delete this.categoryLabel;
+ return (this.categoryLabel = document.getElementById(
+ "identity-popup-content-blocking-cryptominers-state-label"
+ ));
+ },
+
+ get subViewList() {
+ delete this.subViewList;
+ return (this.subViewList = document.getElementById(
+ "identity-popup-cryptominersView-list"
+ ));
+ },
+
+ updateCategoryLabel() {
+ let label;
+ if (this.enabled) {
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.cryptominers.blocking.label"
+ : null;
+ } else {
+ label = ContentBlocking.showAllowedLabels
+ ? "contentBlocking.cryptominers.allowed.label"
+ : null;
+ }
+ this.categoryLabel.textContent = label
+ ? gNavigatorBundle.getString(label)
+ : "";
+ },
+
+ isBlocking(state) {
+ return (
+ (state & Ci.nsIWebProgressListener.STATE_BLOCKED_CRYPTOMINING_CONTENT) !=
+ 0
+ );
+ },
+
+ isAllowing(state) {
+ return (
+ this.enabled &&
+ (state & Ci.nsIWebProgressListener.STATE_LOADED_CRYPTOMINING_CONTENT) != 0
+ );
+ },
+
+ isDetected(state) {
+ return this.isBlocking(state) || this.isAllowing(state);
+ },
+
+ async updateSubView() {
+ let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
+ contentBlockingLog = JSON.parse(contentBlockingLog);
+
+ let fragment = document.createDocumentFragment();
+ for (let [origin, actions] of Object.entries(contentBlockingLog)) {
+ let listItem = this._createListItem(origin, actions);
+ if (listItem) {
+ fragment.appendChild(listItem);
+ }
+ }
+
+ this.subViewList.textContent = "";
+ this.subViewList.append(fragment);
+ },
+
+ _createListItem(origin, actions) {
+ let isAllowed = actions.some(([state]) => this.isAllowing(state));
+ let isDetected =
+ isAllowed || actions.some(([state]) => this.isBlocking(state));
+
+ if (!isDetected) {
+ return null;
+ }
+
+ let uri = Services.io.newURI(origin);
+
+ let listItem = document.createXULElement("hbox");
+ listItem.className = "identity-popup-content-blocking-list-item";
+ listItem.classList.toggle("allowed", isAllowed);
+ // Repeat the host in the tooltip in case it's too long
+ // and overflows in our panel.
+ listItem.tooltipText = uri.host;
+
+ let image = document.createXULElement("image");
+ image.className = "identity-popup-cryptominersView-icon";
+ image.classList.toggle("allowed", isAllowed);
+ listItem.append(image);
+
+ let label = document.createXULElement("label");
+ label.value = uri.host;
+ label.className = "identity-popup-content-blocking-list-host-label";
+ label.setAttribute("crop", "end");
+ listItem.append(label);
+
+ if (!isAllowed) {
+ let stateLabel = document.createXULElement("label");
+ stateLabel.value = this.strings.subViewBlocked;
+ stateLabel.className = "identity-popup-content-blocking-list-state-label";
+ listItem.append(stateLabel);
+ }
+
+ return listItem;
+ },
+};
+
+var TrackingProtection = {
+ reportBreakageLabel: "trackingprotection",
+ telemetryIdentifier: "tp",
+ PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled",
+ PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.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 categoryLabel() {
+ delete this.categoryLabel;
+ return (this.categoryLabel = document.getElementById(
+ "identity-popup-content-blocking-tracking-protection-state-label"
+ ));
+ },
+
+ 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"
+ ));
+ },
+
+ strings: {
+ get subViewBlocked() {
+ delete this.subViewBlocked;
+ return (this.subViewBlocked = gNavigatorBundle.getString(
+ "contentBlocking.trackersView.blocked.label"
+ ));
+ },
+ },
+
+ init() {
+ this.updateEnabled();
+
+ Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
+ Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
+
+ 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() {
+ this.updateEnabled();
+ },
+
+ get enabled() {
+ return (
+ this.enabledGlobally ||
+ (this.enabledInPrivateWindows &&
+ PrivateBrowsingUtils.isWindowPrivate(window))
+ );
+ },
+
+ updateEnabled() {
+ this.enabledGlobally = Services.prefs.getBoolPref(
+ this.PREF_ENABLED_GLOBALLY
+ );
+ this.enabledInPrivateWindows = Services.prefs.getBoolPref(
+ this.PREF_ENABLED_IN_PRIVATE_WINDOWS
+ );
+ this.updateCategoryLabel();
+ },
+
+ updateCategoryLabel() {
+ let label;
+ if (this.enabled) {
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.trackers.blocking.label"
+ : null;
+ } else {
+ label = ContentBlocking.showAllowedLabels
+ ? "contentBlocking.trackers.allowed.label"
+ : null;
+ }
+ this.categoryLabel.textContent = label
+ ? gNavigatorBundle.getString(label)
+ : "";
+ },
+
+ isBlocking(state) {
+ return (
+ (state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) != 0
+ );
+ },
+
+ isAllowing(state) {
+ return (
+ (state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) != 0
+ );
+ },
+
+ isDetected(state) {
+ return this.isBlocking(state) || this.isAllowing(state);
+ },
+
+ async updateSubView() {
+ let previousURI = gBrowser.currentURI.spec;
+ let previousWindow = gBrowser.selectedBrowser.innerWindowID;
+
+ let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
+ contentBlockingLog = JSON.parse(contentBlockingLog);
+
+ // 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);
+ }
+ }
+
+ // If we don't have trackers we would usually not show the menu item
+ // allowing the user to show the sub-panel. However, in the edge case
+ // that we annotated trackers on the page using the strict list but did
+ // not detect trackers on the page using the basic list, we currently
+ // still show the panel. To reduce the confusion, tell the user that we have
+ // not detected any tracker.
+ if (fragment.childNodes.length == 0) {
+ let emptyBox = document.createXULElement("vbox");
+ let emptyImage = document.createXULElement("image");
+ emptyImage.classList.add(
+ "identity-popup-content-blocking-trackersView-empty-image"
+ );
+ emptyImage.classList.add("tracking-protection-icon");
+
+ let emptyLabel = document.createXULElement("label");
+ emptyLabel.classList.add("identity-popup-content-blocking-empty-label");
+ emptyLabel.textContent = gNavigatorBundle.getString(
+ "contentBlocking.trackersView.empty.label"
+ );
+
+ emptyBox.appendChild(emptyImage);
+ emptyBox.appendChild(emptyLabel);
+ fragment.appendChild(emptyBox);
+
+ this.subViewList.classList.add("empty");
+ } else {
+ this.subViewList.classList.remove("empty");
+ }
+
+ // 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;
+ }
+
+ let feature = classifierService.getFeatureByName("tracking-protection");
+ if (!feature) {
+ return false;
+ }
+
+ return new Promise(resolve => {
+ classifierService.asyncClassifyLocalWithFeatures(
+ uri,
+ [feature],
+ Ci.nsIUrlClassifierFeature.blacklist,
+ list => resolve(!!list.length)
+ );
+ });
+ },
+
+ async _createListItem(origin, actions) {
+ // Figure out if this list entry was actually detected by TP or something else.
+ let isAllowed = actions.some(([state]) => this.isAllowing(state));
+ let isDetected =
+ isAllowed || actions.some(([state]) => this.isBlocking(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-content-blocking-list-item";
+ listItem.classList.toggle("allowed", isAllowed);
+ // Repeat the host in the tooltip in case it's too long
+ // and overflows in our panel.
+ listItem.tooltipText = uri.host;
+
+ let image = document.createXULElement("image");
+ image.className = "identity-popup-trackersView-icon";
+ image.classList.toggle("allowed", isAllowed);
+ listItem.append(image);
+
+ let label = document.createXULElement("label");
+ label.value = uri.host;
+ label.className = "identity-popup-content-blocking-list-host-label";
+ label.setAttribute("crop", "end");
+ listItem.append(label);
+
+ if (!isAllowed) {
+ let stateLabel = document.createXULElement("label");
+ stateLabel.value = this.strings.subViewBlocked;
+ stateLabel.className = "identity-popup-content-blocking-list-state-label";
+ listItem.append(stateLabel);
+ }
+
+ 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
+ // of the Preferences UI.
+ Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, // Block all third-party cookies
+ Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER, // Block third-party cookies from trackers
+ ],
+
+ get categoryItem() {
+ delete this.categoryItem;
+ return (this.categoryItem = document.getElementById(
+ "identity-popup-content-blocking-category-cookies"
+ ));
+ },
+
+ get categoryLabel() {
+ delete this.categoryLabel;
+ return (this.categoryLabel = document.getElementById(
+ "identity-popup-content-blocking-cookies-state-label"
+ ));
+ },
+
+ get subViewList() {
+ delete this.subViewList;
+ return (this.subViewList = document.getElementById(
+ "identity-popup-cookiesView-list"
+ ));
+ },
+
+ strings: {
+ get subViewAllowed() {
+ delete this.subViewAllowed;
+ return (this.subViewAllowed = gNavigatorBundle.getString(
+ "contentBlocking.cookiesView.allowed.label"
+ ));
+ },
+
+ get subViewBlocked() {
+ delete this.subViewBlocked;
+ return (this.subViewBlocked = gNavigatorBundle.getString(
+ "contentBlocking.cookiesView.blocked.label"
+ ));
+ },
+ },
+
+ get reportBreakageLabel() {
+ switch (this.behaviorPref) {
+ case Ci.nsICookieService.BEHAVIOR_ACCEPT:
+ return "nocookiesblocked";
+ case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
+ return "allthirdpartycookiesblocked";
+ case Ci.nsICookieService.BEHAVIOR_REJECT:
+ return "allcookiesblocked";
+ case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
+ return "cookiesfromunvisitedsitesblocked";
+ default:
+ Cu.reportError(
+ `Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`
+ );
+ // fall through
+ case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
+ return "cookierestrictions";
+ case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN:
+ return "cookierestrictionsforeignpartitioned";
+ }
+ },
+
+ updateCategoryLabel() {
+ let label;
+ switch (this.behaviorPref) {
+ case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.cookies.blocking3rdParty.label"
+ : null;
+ break;
+ case Ci.nsICookieService.BEHAVIOR_REJECT:
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.cookies.blockingAll.label"
+ : null;
+ break;
+ case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.cookies.blockingUnvisited.label"
+ : null;
+ break;
+ case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
+ label = ContentBlocking.showBlockedLabels
+ ? "contentBlocking.cookies.blockingTrackers.label"
+ : null;
+ break;
+ default:
+ Cu.reportError(
+ `Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`
+ );
+ // fall through
+ case Ci.nsICookieService.BEHAVIOR_ACCEPT:
+ label = ContentBlocking.showAllowedLabels
+ ? "contentBlocking.cookies.allowed.label"
+ : null;
+ break;
+ }
+ this.categoryLabel.textContent = label
+ ? gNavigatorBundle.getString(label)
+ : "";
+ },
+
+ init() {
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "behaviorPref",
+ this.PREF_ENABLED,
+ Ci.nsICookieService.BEHAVIOR_ACCEPT,
+ this.updateCategoryLabel.bind(this)
+ );
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "reportBreakageEnabled",
+ this.PREF_REPORT_BREAKAGE_ENABLED,
+ false
+ );
+ this.updateCategoryLabel();
+ },
+
+ get enabled() {
+ return this.PREF_ENABLED_VALUES.includes(this.behaviorPref);
+ },
+
+ isBlocking(state) {
+ return (
+ (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER) != 0 ||
+ (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_ALL) != 0 ||
+ (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_BY_PERMISSION) !=
+ 0 ||
+ (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_FOREIGN) != 0
+ );
+ },
+
+ isDetected(state) {
+ return (state & Ci.nsIWebProgressListener.STATE_COOKIES_LOADED) != 0;
+ },
+
+ async updateSubView() {
+ let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
+ contentBlockingLog = JSON.parse(contentBlockingLog);
+
+ let categories = this._processContentBlockingLog(contentBlockingLog);
+
+ this.subViewList.textContent = "";
+
+ for (let category of ["firstParty", "trackers", "thirdParty"]) {
+ let box = document.createXULElement("vbox");
+ let label = document.createXULElement("label");
+ label.className = "identity-popup-cookiesView-list-header";
+ label.textContent = gNavigatorBundle.getString(
+ `contentBlocking.cookiesView.${category}.label`
+ );
+ box.appendChild(label);
+
+ for (let info of categories[category]) {
+ box.appendChild(this._createListItem(info));
+ }
+
+ // If the category is empty, add a label noting that to the user.
+ if (categories[category].length == 0) {
+ let emptyLabel = document.createXULElement("label");
+ emptyLabel.classList.add("identity-popup-content-blocking-empty-label");
+ emptyLabel.textContent = gNavigatorBundle.getString(
+ `contentBlocking.cookiesView.${category}.empty.label`
+ );
+ box.appendChild(emptyLabel);
+ }
+
+ this.subViewList.appendChild(box);
+ }
+ },
+
+ _hasException(origin) {
+ for (let perm of Services.perms.getAllForPrincipal(
+ gBrowser.contentPrincipal
+ )) {
+ if (
+ perm.type == "3rdPartyStorage^" + origin ||
+ perm.type.startsWith("3rdPartyStorage^" + origin + "^")
+ ) {
+ return true;
+ }
+ }
+
+ let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
+ origin
+ );
+ // Cookie exceptions get "inherited" from parent- to sub-domain, so we need to
+ // make sure to include parent domains in the permission check for "cookies".
+ return (
+ Services.perms.testPermissionFromPrincipal(principal, "cookie") !=
+ Services.perms.UNKNOWN_ACTION
+ );
+ },
+
+ _clearException(origin) {
+ for (let perm of Services.perms.getAllForPrincipal(
+ gBrowser.contentPrincipal
+ )) {
+ if (
+ perm.type == "3rdPartyStorage^" + origin ||
+ perm.type.startsWith("3rdPartyStorage^" + origin + "^")
+ ) {
+ Services.perms.removePermission(perm);
+ }
+ }
+
+ // OAs don't matter here, so we can just use the hostname.
+ let host = Services.io.newURI(origin).host;
+
+ // Cookie exceptions get "inherited" from parent- to sub-domain, so we need to
+ // clear any cookie permissions from parent domains as well.
+ for (let perm of Services.perms.enumerator) {
+ if (
+ perm.type == "cookie" &&
+ Services.eTLD.hasRootDomain(host, perm.principal.URI.host)
+ ) {
+ Services.perms.removePermission(perm);
+ }
+ }
+ },
+
+ // Transforms and filters cookie entries in the content blocking log
+ // so that we can categorize and display them in the UI.
+ _processContentBlockingLog(log) {
+ let newLog = {
+ firstParty: [],
+ trackers: [],
+ thirdParty: [],
+ };
+
+ let firstPartyDomain = null;
+ try {
+ firstPartyDomain = Services.eTLD.getBaseDomain(gBrowser.currentURI);
+ } catch (e) {
+ // There are nasty edge cases here where someone is trying to set a cookie
+ // on a public suffix or an IP address. Just categorize those as third party...
+ if (
+ e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS &&
+ e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
+ ) {
+ throw e;
+ }
+ }
+
+ for (let [origin, actions] of Object.entries(log)) {
+ if (!origin.startsWith("http")) {
+ continue;
+ }
+
+ let info = {
+ origin,
+ isAllowed: true,
+ hasException: this._hasException(origin),
+ };
+ let hasCookie = false;
+ let isTracker = false;
+
+ // Extract information from the states entries in the content blocking log.
+ // Each state will contain a single state flag from nsIWebProgressListener.
+ // Note that we are using the same helper functions that are applied to the
+ // bit map passed to onSecurityChange (which contains multiple states), thus
+ // not checking exact equality, just presence of bits.
+ for (let [state, blocked] of actions) {
+ if (this.isDetected(state)) {
+ hasCookie = true;
+ }
+ if (TrackingProtection.isAllowing(state)) {
+ isTracker = true;
+ }
+ // blocked tells us whether the resource was actually blocked
+ // (which it may not be in case of an exception).
+ if (this.isBlocking(state)) {
+ info.isAllowed = !blocked;
+ }
+ }
+
+ if (!hasCookie) {
+ continue;
+ }
+
+ let isFirstParty = false;
+ try {
+ let uri = Services.io.newURI(origin);
+ isFirstParty = Services.eTLD.getBaseDomain(uri) == firstPartyDomain;
+ } catch (e) {
+ if (
+ e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS &&
+ e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
+ ) {
+ throw e;
+ }
+ }
+
+ if (isFirstParty) {
+ newLog.firstParty.push(info);
+ } else if (isTracker) {
+ newLog.trackers.push(info);
+ } else {
+ newLog.thirdParty.push(info);
+ }
+ }
+
+ return newLog;
+ },
+
+ _createListItem({ origin, isAllowed, hasException }) {
+ let listItem = document.createXULElement("hbox");
+ listItem.className = "identity-popup-content-blocking-list-item";
+ listItem.classList.toggle("allowed", isAllowed);
+ // Repeat the origin in the tooltip in case it's too long
+ // and overflows in our panel.
+ listItem.tooltipText = origin;
+
+ let image = document.createXULElement("image");
+ image.className = "identity-popup-cookiesView-icon";
+ image.classList.toggle("allowed", isAllowed);
+ listItem.append(image);
+
+ let label = document.createXULElement("label");
+ label.value = origin;
+ label.className = "identity-popup-content-blocking-list-host-label";
+ label.setAttribute("crop", "end");
+ listItem.append(label);
+
+ let stateLabel;
+ if (isAllowed && hasException) {
+ stateLabel = document.createXULElement("label");
+ stateLabel.value = this.strings.subViewAllowed;
+ stateLabel.className = "identity-popup-content-blocking-list-state-label";
+ listItem.append(stateLabel);
+ } else if (!isAllowed) {
+ stateLabel = document.createXULElement("label");
+ stateLabel.value = this.strings.subViewBlocked;
+ stateLabel.className = "identity-popup-content-blocking-list-state-label";
+ listItem.append(stateLabel);
+ }
+
+ if (hasException) {
+ let removeException = document.createXULElement("button");
+ removeException.className = "identity-popup-permission-remove-button";
+ removeException.tooltipText = gNavigatorBundle.getFormattedString(
+ "contentBlocking.cookiesView.removeButton.tooltip",
+ [origin]
+ );
+ removeException.addEventListener("click", () => {
+ this._clearException(origin);
+ // Just flip the display based on what state we had previously.
+ stateLabel.value = isAllowed
+ ? this.strings.subViewBlocked
+ : this.strings.subViewAllowed;
+ listItem.classList.toggle("allowed", !isAllowed);
+ image.classList.toggle("allowed", !isAllowed);
+ removeException.hidden = true;
+ });
+ listItem.append(removeException);
+ }
+
+ return listItem;
+ },
+};
+
+var ContentBlocking = {
+ PREF_ANIMATIONS_ENABLED: "toolkit.cosmeticAnimations.enabled",
+ PREF_REPORT_BREAKAGE_ENABLED:
+ "browser.contentblocking.reportBreakage.enabled",
+ PREF_REPORT_BREAKAGE_URL: "browser.contentblocking.reportBreakage.url",
+ PREF_CB_CATEGORY: "browser.contentblocking.category",
+ PREF_SHOW_ALLOWED_LABELS:
+ "browser.contentblocking.control-center.ui.showAllowedLabels",
+ PREF_SHOW_BLOCKED_LABELS:
+ "browser.contentblocking.control-center.ui.showBlockedLabels",
+
+ get content() {
+ delete this.content;
+ return (this.content = document.getElementById(
+ "identity-popup-content-blocking-content"
+ ));
+ },
+
+ get icon() {
+ delete this.icon;
+ return (this.icon = document.getElementById("tracking-protection-icon"));
+ },
+
+ get iconBox() {
+ delete this.iconBox;
+ return (this.iconBox = document.getElementById(
+ "tracking-protection-icon-box"
+ ));
+ },
+
+ get animatedIcon() {
+ delete this.animatedIcon;
+ return (this.animatedIcon = document.getElementById(
+ "tracking-protection-icon-animatable-image"
+ ));
+ },
+
+ get identityPopupMultiView() {
+ delete this.identityPopupMultiView;
+ return (this.identityPopupMultiView = document.getElementById(
+ "identity-popup-multiView"
+ ));
+ },
+
+ get reportBreakageButton() {
+ delete this.reportBreakageButton;
+ return (this.reportBreakageButton = document.getElementById(
+ "identity-popup-content-blocking-report-breakage"
+ ));
+ },
+
+ get reportBreakageURL() {
+ delete this.reportBreakageURL;
+ return (this.reportBreakageURL = document.getElementById(
+ "identity-popup-breakageReportView-collection-url"
+ ));
+ },
+
+ get reportBreakageLearnMore() {
+ delete this.reportBreakageLearnMore;
+ return (this.reportBreakageLearnMore = document.getElementById(
+ "identity-popup-breakageReportView-learn-more"
+ ));
+ },
+
+ 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"));
+ },
+
+ get protectionsPopup() {
+ delete this.protectionsPopup;
+ return (this.protectionsPopup = document.getElementById(
+ "protections-popup"
+ ));
+ },
+
+ strings: {
+ get appMenuTitle() {
+ delete this.appMenuTitle;
+ return (this.appMenuTitle = gNavigatorBundle.getString(
+ "contentBlocking.title"
+ ));
+ },
+
+ get appMenuTooltip() {
+ delete this.appMenuTooltip;
+ if (AppConstants.platform == "win") {
+ return (this.appMenuTooltip = gNavigatorBundle.getString(
+ "contentBlocking.tooltipWin"
+ ));
+ }
+ return (this.appMenuTooltip = gNavigatorBundle.getString(
+ "contentBlocking.tooltipOther"
+ ));
+ },
+
+ get activeTooltipText() {
+ delete this.activeTooltipText;
+ return (this.activeTooltipText = gNavigatorBundle.getString(
+ "trackingProtection.icon.activeTooltip"
+ ));
+ },
+
+ get disabledTooltipText() {
+ delete this.disabledTooltipText;
+ return (this.disabledTooltipText = gNavigatorBundle.getString(
+ "trackingProtection.icon.disabledTooltip"
+ ));
+ },
+ },
+
+ // A list of blockers that will be displayed in the categories list
+ // when blockable content is detected. A blocker must be an object
+ // with at least the following two properties:
+ // - enabled: Whether the blocker is currently turned on.
+ // - isDetected(state): Given a content blocking state, whether the blocker has
+ // either allowed or blocked elements.
+ // - categoryItem: The DOM item that represents the entry in the category list.
+ //
+ // It may also contain an init() and uninit() function, which will be called
+ // on ContentBlocking.init() and ContentBlocking.uninit().
+ blockers: [
+ TrackingProtection,
+ ThirdPartyCookies,
+ Fingerprinting,
+ Cryptomining,
+ ],
+
+ get _baseURIForChannelClassifier() {
+ // Convert document URI into the format used by
+ // nsChannelClassifier::ShouldEnableTrackingProtection.
+ // Any scheme turned into https is correct.
+ try {
+ return Services.io.newURI(
+ "https://" + gBrowser.selectedBrowser.currentURI.hostPort
+ );
+ } catch (e) {
+ // Getting the hostPort for about: and file: URIs fails, but TP doesn't work with
+ // these URIs anyway, so just return null here.
+ return null;
+ }
+ },
+
+ init() {
+ this.animatedIcon.addEventListener("animationend", () =>
+ this.iconBox.removeAttribute("animate")
+ );
+
+ let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
+ this.reportBreakageLearnMore.href = baseURL + "blocking-breakage";
+
+ this.updateAnimationsEnabled = () => {
+ this.iconBox.toggleAttribute(
+ "animationsenabled",
+ Services.prefs.getBoolPref(this.PREF_ANIMATIONS_ENABLED, false)
+ );
+ };
+
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "showBlockedLabels",
+ this.PREF_SHOW_BLOCKED_LABELS,
+ false,
+ () => {
+ for (let blocker of this.blockers) {
+ blocker.updateCategoryLabel();
+ }
+ }
+ );
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "showAllowedLabels",
+ this.PREF_SHOW_ALLOWED_LABELS,
+ false,
+ () => {
+ for (let blocker of this.blockers) {
+ blocker.updateCategoryLabel();
+ }
+ }
+ );
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "reportBreakageEnabled",
+ this.PREF_REPORT_BREAKAGE_ENABLED,
+ false
+ );
+
+ for (let blocker of this.blockers) {
+ if (blocker.init) {
+ blocker.init();
+ }
+ }
+
+ this.updateAnimationsEnabled();
+
+ Services.prefs.addObserver(
+ this.PREF_ANIMATIONS_ENABLED,
+ this.updateAnimationsEnabled
+ );
+
+ this.appMenuLabel.setAttribute("value", this.strings.appMenuTitle);
+ this.appMenuLabel.setAttribute("tooltiptext", this.strings.appMenuTooltip);
+
+ this.updateCBCategoryLabel = this.updateCBCategoryLabel.bind(this);
+ this.updateCBCategoryLabel();
+ Services.prefs.addObserver(
+ this.PREF_CB_CATEGORY,
+ this.updateCBCategoryLabel
+ );
+ },
+
+ uninit() {
+ for (let blocker of this.blockers) {
+ if (blocker.uninit) {
+ blocker.uninit();
+ }
+ }
+
+ Services.prefs.removeObserver(
+ this.PREF_ANIMATIONS_ENABLED,
+ this.updateAnimationsEnabled
+ );
+ Services.prefs.removeObserver(
+ this.PREF_CB_CATEGORY,
+ this.updateCBCategoryLabel
+ );
+ },
+
+ updateCBCategoryLabel() {
+ if (!Services.prefs.prefHasUserValue(this.PREF_CB_CATEGORY)) {
+ // Fallback to not setting a label, it's preferable to not set a label than to set an incorrect one.
+ return;
+ }
+ let button = document.getElementById(
+ "tracking-protection-preferences-button"
+ );
+ let appMenuCategoryLabel = document.getElementById("appMenu-tp-category");
+ let label;
+ let category = Services.prefs.getStringPref(this.PREF_CB_CATEGORY);
+ switch (category) {
+ case "standard":
+ label = gNavigatorBundle.getString("contentBlocking.category.standard");
+ break;
+ case "strict":
+ label = gNavigatorBundle.getString("contentBlocking.category.strict");
+ break;
+ case "custom":
+ label = gNavigatorBundle.getString("contentBlocking.category.custom");
+ break;
+ }
+ appMenuCategoryLabel.value = label;
+ button.label = label;
+ },
+
+ hideIdentityPopupAndReload() {
+ this.identityPopup.hidePopup();
+ BrowserReload();
+ },
+
+ openPreferences(origin) {
+ openPreferences("privacy-trackingprotection", { origin });
+ },
+
+ backToMainView() {
+ this.identityPopupMultiView.goBack();
+ },
+
+ onSubmitBreakageReportClicked() {
+ this.identityPopup.hidePopup();
+
+ let comments = document.getElementById(
+ "identity-popup-breakageReportView-collection-comments"
+ );
+ this.submitBreakageReport(this.reportURI, comments);
+ },
+
+ submitBreakageReport(uri, commentsTextarea) {
+ let reportEndpoint = Services.prefs.getStringPref(
+ this.PREF_REPORT_BREAKAGE_URL
+ );
+ if (!reportEndpoint) {
+ return;
+ }
+
+ let formData = new FormData();
+ formData.set("title", uri.host);
+
+ // Leave the ? at the end of the URL to signify that this URL had its query stripped.
+ let urlWithoutQuery = uri.asciiSpec.replace(uri.query, "");
+ let body = `Full URL: ${urlWithoutQuery}\n`;
+ body += `userAgent: ${navigator.userAgent}\n`;
+
+ body += "\n**Preferences**\n";
+ body += `${
+ TrackingProtection.PREF_ENABLED_GLOBALLY
+ }: ${Services.prefs.getBoolPref(
+ TrackingProtection.PREF_ENABLED_GLOBALLY
+ )}\n`;
+ body += `${
+ TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS
+ }: ${Services.prefs.getBoolPref(
+ TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS
+ )}\n`;
+ body += `urlclassifier.trackingTable: ${Services.prefs.getStringPref(
+ "urlclassifier.trackingTable"
+ )}\n`;
+ body += `network.http.referer.defaultPolicy: ${Services.prefs.getIntPref(
+ "network.http.referer.defaultPolicy"
+ )}\n`;
+ body += `network.http.referer.defaultPolicy.pbmode: ${Services.prefs.getIntPref(
+ "network.http.referer.defaultPolicy.pbmode"
+ )}\n`;
+ body += `${ThirdPartyCookies.PREF_ENABLED}: ${Services.prefs.getIntPref(
+ ThirdPartyCookies.PREF_ENABLED
+ )}\n`;
+ body += `network.cookie.lifetimePolicy: ${Services.prefs.getIntPref(
+ "network.cookie.lifetimePolicy"
+ )}\n`;
+ body += `privacy.annotate_channels.strict_list.enabled: ${Services.prefs.getBoolPref(
+ "privacy.annotate_channels.strict_list.enabled"
+ )}\n`;
+ body += `privacy.restrict3rdpartystorage.expiration: ${Services.prefs.getIntPref(
+ "privacy.restrict3rdpartystorage.expiration"
+ )}\n`;
+ body += `${Fingerprinting.PREF_ENABLED}: ${Services.prefs.getBoolPref(
+ Fingerprinting.PREF_ENABLED
+ )}\n`;
+ body += `${Cryptomining.PREF_ENABLED}: ${Services.prefs.getBoolPref(
+ Cryptomining.PREF_ENABLED
+ )}\n`;
+
+ body += "\n**Comments**\n" + commentsTextarea.value;
+
+ formData.set("body", body);
+
+ let activatedBlockers = [];
+ for (let blocker of this.blockers) {
+ if (blocker.activated) {
+ activatedBlockers.push(blocker.reportBreakageLabel);
+ }
+ }
+
+ if (activatedBlockers.length) {
+ formData.set("labels", activatedBlockers.join(","));
+ }
+
+ fetch(reportEndpoint, {
+ method: "POST",
+ credentials: "omit",
+ body: formData,
+ })
+ .then(function(response) {
+ if (!response.ok) {
+ Cu.reportError(
+ `Content Blocking report to ${reportEndpoint} failed with status ${
+ response.status
+ }`
+ );
+ } else {
+ // Clear the textarea value when the report is submitted
+ commentsTextarea.value = "";
+ }
+ })
+ .catch(Cu.reportError);
+ },
+
+ toggleReportBreakageButton() {
+ // For release (due to the large volume) we only want to receive reports
+ // for breakage that is directly related to third party cookie blocking.
+ if (
+ this.reportBreakageEnabled ||
+ (ThirdPartyCookies.reportBreakageEnabled &&
+ ThirdPartyCookies.activated &&
+ !TrackingProtection.activated)
+ ) {
+ this.reportBreakageButton.removeAttribute("hidden");
+ } else {
+ this.reportBreakageButton.setAttribute("hidden", "true");
+ }
+ },
+
+ showReportBreakageSubview() {
+ // 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.value = urlWithoutQuery;
+ this.identityPopupMultiView.showSubView(
+ "identity-popup-breakageReportView"
+ );
+ },
+
+ async showTrackersSubview() {
+ await TrackingProtection.updateSubView();
+ this.identityPopupMultiView.showSubView("identity-popup-trackersView");
+ },
+
+ async showCookiesSubview() {
+ await ThirdPartyCookies.updateSubView();
+ this.identityPopupMultiView.showSubView("identity-popup-cookiesView");
+ },
+
+ async showFingerprintersSubview() {
+ await Fingerprinting.updateSubView();
+ this.identityPopupMultiView.showSubView(
+ "identity-popup-fingerprintersView"
+ );
+ },
+
+ async showCryptominersSubview() {
+ await Cryptomining.updateSubView();
+ this.identityPopupMultiView.showSubView("identity-popup-cryptominersView");
+ },
+
+ shieldHistogramAdd(value) {
+ if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+ return;
+ }
+ Services.telemetry
+ .getHistogramById("TRACKING_PROTECTION_SHIELD")
+ .add(value);
+ },
+
+ cryptominersHistogramAdd(value) {
+ Services.telemetry
+ .getHistogramById("CRYPTOMINERS_BLOCKED_COUNT")
+ .add(value);
+ },
+
+ fingerprintersHistogramAdd(value) {
+ Services.telemetry
+ .getHistogramById("FINGERPRINTERS_BLOCKED_COUNT")
+ .add(value);
+ },
+
+ // This triggers from top level location changes.
+ onLocationChange() {
+ // Reset blocking and exception status so that we can send telemetry
+ this.hadShieldState = false;
+
+ // Don't deal with about:, file: etc.
+ if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
+ return;
+ }
+
+ // Check whether the user has added an exception for this site.
+ let hasException = ContentBlockingAllowList.includes(
+ gBrowser.selectedBrowser
+ );
+
+ this.content.toggleAttribute("hasException", hasException);
+ this.protectionsPopup.toggleAttribute("hasException", hasException);
+ this.iconBox.toggleAttribute("hasException", hasException);
+
+ // Add to telemetry per page load as a baseline measurement.
+ this.fingerprintersHistogramAdd("pageLoad");
+ this.cryptominersHistogramAdd("pageLoad");
+ this.shieldHistogramAdd(0);
+ },
+
+ onContentBlockingEvent(event, webProgress, isSimulated) {
+ let previousState = gBrowser.securityUI.contentBlockingEvent;
+
+ // Don't deal with about:, file: etc.
+ if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
+ this.iconBox.removeAttribute("animate");
+ this.iconBox.removeAttribute("active");
+ this.iconBox.removeAttribute("hasException");
+ return;
+ }
+
+ let anyDetected = false;
+ let anyBlocking = false;
+
+ for (let blocker of this.blockers) {
+ // Store data on whether the blocker is activated in the current document for
+ // reporting it using the "report breakage" dialog. Under normal circumstances this
+ // dialog should only be able to open in the currently selected tab and onSecurityChange
+ // runs on tab switch, so we can avoid associating the data with the document directly.
+ blocker.activated = blocker.isBlocking(event);
+ blocker.categoryItem.classList.toggle("blocked", blocker.enabled);
+ let detected = blocker.isDetected(event);
+ blocker.categoryItem.hidden = !detected;
+ anyDetected = anyDetected || detected;
+ anyBlocking = anyBlocking || blocker.activated;
+ }
+
+ // Check whether the user has added an exception for this site.
+ let hasException = ContentBlockingAllowList.includes(
+ gBrowser.selectedBrowser
+ );
+
+ // Reset the animation in case the user is switching tabs or if no blockers were detected
+ // (this is most likely happening because the user navigated on to a different site). This
+ // allows us to play it from the start without choppiness next time.
+ if (isSimulated || !anyBlocking) {
+ this.iconBox.removeAttribute("animate");
+ // Only play the animation when the shield is not already shown on the page (the visibility
+ // of the shield based on this onSecurityChange be determined afterwards).
+ } else if (anyBlocking && !this.iconBox.hasAttribute("active")) {
+ this.iconBox.setAttribute("animate", "true");
+ }
+
+ // We consider the shield state "active" when some kind of blocking activity
+ // occurs on the page. Note that merely allowing the loading of content that
+ // we could have blocked does not trigger the appearance of the shield.
+ // This state will be overriden later if there's an exception set for this site.
+ for (let elt of [this.content, this.protectionsPopup]) {
+ elt.toggleAttribute("detected", anyDetected);
+ elt.toggleAttribute("blocking", anyBlocking);
+ elt.toggleAttribute("hasException", hasException);
+ }
+
+ this.iconBox.toggleAttribute("active", anyBlocking);
+ this.iconBox.toggleAttribute("hasException", hasException);
+
+ if (hasException) {
+ this.iconBox.setAttribute(
+ "tooltiptext",
+ this.strings.disabledTooltipText
+ );
+ if (!this.hadShieldState && !isSimulated) {
+ this.hadShieldState = true;
+ this.shieldHistogramAdd(1);
+ }
+ } else if (anyBlocking) {
+ this.iconBox.setAttribute("tooltiptext", this.strings.activeTooltipText);
+ if (!this.hadShieldState && !isSimulated) {
+ this.hadShieldState = true;
+ this.shieldHistogramAdd(2);
+ }
+ } else {
+ this.iconBox.removeAttribute("tooltiptext");
+ }
+
+ // We report up to one instance of fingerprinting and cryptomining
+ // blocking and/or allowing per page load.
+ let fingerprintingBlocking =
+ Fingerprinting.isBlocking(event) &&
+ !Fingerprinting.isBlocking(previousState);
+ let fingerprintingAllowing =
+ Fingerprinting.isAllowing(event) &&
+ !Fingerprinting.isAllowing(previousState);
+ let cryptominingBlocking =
+ Cryptomining.isBlocking(event) && !Cryptomining.isBlocking(previousState);
+ let cryptominingAllowing =
+ Cryptomining.isAllowing(event) && !Cryptomining.isAllowing(previousState);
+
+ if (fingerprintingBlocking) {
+ this.fingerprintersHistogramAdd("blocked");
+ } else if (fingerprintingAllowing) {
+ this.fingerprintersHistogramAdd("allowed");
+ }
+
+ if (cryptominingBlocking) {
+ this.cryptominersHistogramAdd("blocked");
+ } else if (cryptominingAllowing) {
+ this.cryptominersHistogramAdd("allowed");
+ }
+ },
+
+ disableForCurrentPage() {
+ ContentBlockingAllowList.add(gBrowser.selectedBrowser);
+
+ this.hideIdentityPopupAndReload();
+ },
+
+ enableForCurrentPage() {
+ ContentBlockingAllowList.remove(gBrowser.selectedBrowser);
+
+ this.hideIdentityPopupAndReload();
+ },
+};
diff --git a/browser/base/content/browser-siteIdentity.js b/browser/base/content/browser-siteIdentity.js
index 18cf45a2fbe2..4572d290d8e4 100644
--- a/browser/base/content/browser-siteIdentity.js
+++ b/browser/base/content/browser-siteIdentity.js
@@ -343,10 +343,20 @@ var gIdentityHandler = {
},
recordClick(object) {
+ let extra = {};
+ for (let blocker of ContentBlocking.blockers) {
+ if (blocker.telemetryIdentifier) {
+ extra[blocker.telemetryIdentifier] = blocker.activated
+ ? "true"
+ : "false";
+ }
+ }
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"click",
- object
+ object,
+ null,
+ extra
);
},
@@ -959,6 +969,8 @@ var gIdentityHandler = {
// Update per-site permissions section.
this.updateSitePermissions();
+
+ ContentBlocking.toggleReportBreakageButton();
},
setURI(uri) {
@@ -1089,10 +1101,24 @@ var gIdentityHandler = {
window.addEventListener("focus", this, true);
}
+ let extra = {};
+ for (let blocker of ContentBlocking.blockers) {
+ if (blocker.telemetryIdentifier) {
+ extra[blocker.telemetryIdentifier] = blocker.activated
+ ? "true"
+ : "false";
+ }
+ }
+
+ let shieldStatus = ContentBlocking.iconBox.hasAttribute("active")
+ ? "shield-showing"
+ : "shield-hidden";
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"open",
- "identity_popup"
+ "identity_popup",
+ shieldStatus,
+ extra
);
},
diff --git a/browser/base/content/browser-siteProtections.js b/browser/base/content/browser-siteProtections.js
index 103df16f4807..bdef5251039f 100644
--- a/browser/base/content/browser-siteProtections.js
+++ b/browser/base/content/browser-siteProtections.js
@@ -4,920 +4,10 @@
/* eslint-env mozilla/browser-window */
-ChromeUtils.defineModuleGetter(
- this,
- "ContentBlockingAllowList",
- "resource://gre/modules/ContentBlockingAllowList.jsm"
-);
-
-var Fingerprinting = {
- PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
- reportBreakageLabel: "fingerprinting",
-
- strings: {
- get subViewBlocked() {
- delete this.subViewBlocked;
- return (this.subViewBlocked = gNavigatorBundle.getString(
- "contentBlocking.fingerprintersView.blocked.label"
- ));
- },
- },
-
- init() {
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "enabled",
- this.PREF_ENABLED,
- false,
- () => this.updateCategoryLabel()
- );
- this.updateCategoryLabel();
- },
-
- get categoryItem() {
- delete this.categoryItem;
- return (this.categoryItem = document.getElementById(
- "identity-popup-content-blocking-category-fingerprinters"
- ));
- },
-
- get categoryLabel() {
- delete this.categoryLabel;
- return (this.categoryLabel = document.getElementById(
- "identity-popup-content-blocking-fingerprinters-state-label"
- ));
- },
-
- get subViewList() {
- delete this.subViewList;
- return (this.subViewList = document.getElementById(
- "identity-popup-fingerprintersView-list"
- ));
- },
-
- updateCategoryLabel() {
- let label;
- if (this.enabled) {
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.fingerprinters.blocking.label"
- : null;
- } else {
- label = gProtectionsHandler.showAllowedLabels
- ? "contentBlocking.fingerprinters.allowed.label"
- : null;
- }
- this.categoryLabel.textContent = label
- ? gNavigatorBundle.getString(label)
- : "";
- },
-
- isBlocking(state) {
- return (
- (state &
- Ci.nsIWebProgressListener.STATE_BLOCKED_FINGERPRINTING_CONTENT) !=
- 0
- );
- },
-
- isAllowing(state) {
- return (
- this.enabled &&
- (state & Ci.nsIWebProgressListener.STATE_LOADED_FINGERPRINTING_CONTENT) !=
- 0
- );
- },
-
- isDetected(state) {
- return this.isBlocking(state) || this.isAllowing(state);
- },
-
- async updateSubView() {
- let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
- contentBlockingLog = JSON.parse(contentBlockingLog);
-
- let fragment = document.createDocumentFragment();
- for (let [origin, actions] of Object.entries(contentBlockingLog)) {
- let listItem = this._createListItem(origin, actions);
- if (listItem) {
- fragment.appendChild(listItem);
- }
- }
-
- this.subViewList.textContent = "";
- this.subViewList.append(fragment);
- },
-
- _createListItem(origin, actions) {
- let isAllowed = actions.some(([state]) => this.isAllowing(state));
- let isDetected =
- isAllowed || actions.some(([state]) => this.isBlocking(state));
-
- if (!isDetected) {
- return null;
- }
-
- let uri = Services.io.newURI(origin);
-
- let listItem = document.createXULElement("hbox");
- listItem.className = "identity-popup-content-blocking-list-item";
- listItem.classList.toggle("allowed", isAllowed);
- // Repeat the host in the tooltip in case it's too long
- // and overflows in our panel.
- listItem.tooltipText = uri.host;
-
- let image = document.createXULElement("image");
- image.className = "identity-popup-fingerprintersView-icon";
- image.classList.toggle("allowed", isAllowed);
- listItem.append(image);
-
- let label = document.createXULElement("label");
- label.value = uri.host;
- label.className = "identity-popup-content-blocking-list-host-label";
- label.setAttribute("crop", "end");
- listItem.append(label);
-
- if (!isAllowed) {
- let stateLabel = document.createXULElement("label");
- stateLabel.value = this.strings.subViewBlocked;
- stateLabel.className = "identity-popup-content-blocking-list-state-label";
- listItem.append(stateLabel);
- }
-
- return listItem;
- },
-};
-
-var Cryptomining = {
- PREF_ENABLED: "privacy.trackingprotection.cryptomining.enabled",
- reportBreakageLabel: "cryptomining",
-
- strings: {
- get subViewBlocked() {
- delete this.subViewBlocked;
- return (this.subViewBlocked = gNavigatorBundle.getString(
- "contentBlocking.cryptominersView.blocked.label"
- ));
- },
- },
-
- init() {
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "enabled",
- this.PREF_ENABLED,
- false,
- () => this.updateCategoryLabel()
- );
- this.updateCategoryLabel();
- },
-
- get categoryItem() {
- delete this.categoryItem;
- return (this.categoryItem = document.getElementById(
- "identity-popup-content-blocking-category-cryptominers"
- ));
- },
-
- get categoryLabel() {
- delete this.categoryLabel;
- return (this.categoryLabel = document.getElementById(
- "identity-popup-content-blocking-cryptominers-state-label"
- ));
- },
-
- get subViewList() {
- delete this.subViewList;
- return (this.subViewList = document.getElementById(
- "identity-popup-cryptominersView-list"
- ));
- },
-
- updateCategoryLabel() {
- let label;
- if (this.enabled) {
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.cryptominers.blocking.label"
- : null;
- } else {
- label = gProtectionsHandler.showAllowedLabels
- ? "contentBlocking.cryptominers.allowed.label"
- : null;
- }
- this.categoryLabel.textContent = label
- ? gNavigatorBundle.getString(label)
- : "";
- },
-
- isBlocking(state) {
- return (
- (state & Ci.nsIWebProgressListener.STATE_BLOCKED_CRYPTOMINING_CONTENT) !=
- 0
- );
- },
-
- isAllowing(state) {
- return (
- this.enabled &&
- (state & Ci.nsIWebProgressListener.STATE_LOADED_CRYPTOMINING_CONTENT) != 0
- );
- },
-
- isDetected(state) {
- return this.isBlocking(state) || this.isAllowing(state);
- },
-
- async updateSubView() {
- let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
- contentBlockingLog = JSON.parse(contentBlockingLog);
-
- let fragment = document.createDocumentFragment();
- for (let [origin, actions] of Object.entries(contentBlockingLog)) {
- let listItem = this._createListItem(origin, actions);
- if (listItem) {
- fragment.appendChild(listItem);
- }
- }
-
- this.subViewList.textContent = "";
- this.subViewList.append(fragment);
- },
-
- _createListItem(origin, actions) {
- let isAllowed = actions.some(([state]) => this.isAllowing(state));
- let isDetected =
- isAllowed || actions.some(([state]) => this.isBlocking(state));
-
- if (!isDetected) {
- return null;
- }
-
- let uri = Services.io.newURI(origin);
-
- let listItem = document.createXULElement("hbox");
- listItem.className = "identity-popup-content-blocking-list-item";
- listItem.classList.toggle("allowed", isAllowed);
- // Repeat the host in the tooltip in case it's too long
- // and overflows in our panel.
- listItem.tooltipText = uri.host;
-
- let image = document.createXULElement("image");
- image.className = "identity-popup-cryptominersView-icon";
- image.classList.toggle("allowed", isAllowed);
- listItem.append(image);
-
- let label = document.createXULElement("label");
- label.value = uri.host;
- label.className = "identity-popup-content-blocking-list-host-label";
- label.setAttribute("crop", "end");
- listItem.append(label);
-
- if (!isAllowed) {
- let stateLabel = document.createXULElement("label");
- stateLabel.value = this.strings.subViewBlocked;
- stateLabel.className = "identity-popup-content-blocking-list-state-label";
- listItem.append(stateLabel);
- }
-
- return listItem;
- },
-};
-
-var TrackingProtection = {
- reportBreakageLabel: "trackingprotection",
- PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled",
- PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.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 categoryLabel() {
- delete this.categoryLabel;
- return (this.categoryLabel = document.getElementById(
- "identity-popup-content-blocking-tracking-protection-state-label"
- ));
- },
-
- 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"
- ));
- },
-
- strings: {
- get subViewBlocked() {
- delete this.subViewBlocked;
- return (this.subViewBlocked = gNavigatorBundle.getString(
- "contentBlocking.trackersView.blocked.label"
- ));
- },
- },
-
- init() {
- this.updateEnabled();
-
- Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
- Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
-
- 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() {
- this.updateEnabled();
- },
-
- get enabled() {
- return (
- this.enabledGlobally ||
- (this.enabledInPrivateWindows &&
- PrivateBrowsingUtils.isWindowPrivate(window))
- );
- },
-
- updateEnabled() {
- this.enabledGlobally = Services.prefs.getBoolPref(
- this.PREF_ENABLED_GLOBALLY
- );
- this.enabledInPrivateWindows = Services.prefs.getBoolPref(
- this.PREF_ENABLED_IN_PRIVATE_WINDOWS
- );
- this.updateCategoryLabel();
- },
-
- updateCategoryLabel() {
- let label;
- if (this.enabled) {
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.trackers.blocking.label"
- : null;
- } else {
- label = gProtectionsHandler.showAllowedLabels
- ? "contentBlocking.trackers.allowed.label"
- : null;
- }
- this.categoryLabel.textContent = label
- ? gNavigatorBundle.getString(label)
- : "";
- },
-
- isBlocking(state) {
- return (
- (state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) != 0
- );
- },
-
- isAllowing(state) {
- return (
- (state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) != 0
- );
- },
-
- isDetected(state) {
- return this.isBlocking(state) || this.isAllowing(state);
- },
-
- async updateSubView() {
- let previousURI = gBrowser.currentURI.spec;
- let previousWindow = gBrowser.selectedBrowser.innerWindowID;
-
- let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
- contentBlockingLog = JSON.parse(contentBlockingLog);
-
- // 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);
- }
- }
-
- // If we don't have trackers we would usually not show the menu item
- // allowing the user to show the sub-panel. However, in the edge case
- // that we annotated trackers on the page using the strict list but did
- // not detect trackers on the page using the basic list, we currently
- // still show the panel. To reduce the confusion, tell the user that we have
- // not detected any tracker.
- if (fragment.childNodes.length == 0) {
- let emptyBox = document.createXULElement("vbox");
- let emptyImage = document.createXULElement("image");
- emptyImage.classList.add(
- "identity-popup-content-blocking-trackersView-empty-image"
- );
- emptyImage.classList.add("tracking-protection-icon");
-
- let emptyLabel = document.createXULElement("label");
- emptyLabel.classList.add("identity-popup-content-blocking-empty-label");
- emptyLabel.textContent = gNavigatorBundle.getString(
- "contentBlocking.trackersView.empty.label"
- );
-
- emptyBox.appendChild(emptyImage);
- emptyBox.appendChild(emptyLabel);
- fragment.appendChild(emptyBox);
-
- this.subViewList.classList.add("empty");
- } else {
- this.subViewList.classList.remove("empty");
- }
-
- // 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;
- }
-
- let feature = classifierService.getFeatureByName("tracking-protection");
- if (!feature) {
- return false;
- }
-
- return new Promise(resolve => {
- classifierService.asyncClassifyLocalWithFeatures(
- uri,
- [feature],
- Ci.nsIUrlClassifierFeature.blacklist,
- list => resolve(!!list.length)
- );
- });
- },
-
- async _createListItem(origin, actions) {
- // Figure out if this list entry was actually detected by TP or something else.
- let isAllowed = actions.some(([state]) => this.isAllowing(state));
- let isDetected =
- isAllowed || actions.some(([state]) => this.isBlocking(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-content-blocking-list-item";
- listItem.classList.toggle("allowed", isAllowed);
- // Repeat the host in the tooltip in case it's too long
- // and overflows in our panel.
- listItem.tooltipText = uri.host;
-
- let image = document.createXULElement("image");
- image.className = "identity-popup-trackersView-icon";
- image.classList.toggle("allowed", isAllowed);
- listItem.append(image);
-
- let label = document.createXULElement("label");
- label.value = uri.host;
- label.className = "identity-popup-content-blocking-list-host-label";
- label.setAttribute("crop", "end");
- listItem.append(label);
-
- if (!isAllowed) {
- let stateLabel = document.createXULElement("label");
- stateLabel.value = this.strings.subViewBlocked;
- stateLabel.className = "identity-popup-content-blocking-list-state-label";
- listItem.append(stateLabel);
- }
-
- return listItem;
- },
-};
-
-var ThirdPartyCookies = {
- 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
- // of the Preferences UI.
- Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, // Block all third-party cookies
- Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER, // Block third-party cookies from trackers
- ],
-
- get categoryItem() {
- delete this.categoryItem;
- return (this.categoryItem = document.getElementById(
- "identity-popup-content-blocking-category-cookies"
- ));
- },
-
- get categoryLabel() {
- delete this.categoryLabel;
- return (this.categoryLabel = document.getElementById(
- "identity-popup-content-blocking-cookies-state-label"
- ));
- },
-
- get subViewList() {
- delete this.subViewList;
- return (this.subViewList = document.getElementById(
- "identity-popup-cookiesView-list"
- ));
- },
-
- strings: {
- get subViewAllowed() {
- delete this.subViewAllowed;
- return (this.subViewAllowed = gNavigatorBundle.getString(
- "contentBlocking.cookiesView.allowed.label"
- ));
- },
-
- get subViewBlocked() {
- delete this.subViewBlocked;
- return (this.subViewBlocked = gNavigatorBundle.getString(
- "contentBlocking.cookiesView.blocked.label"
- ));
- },
- },
-
- get reportBreakageLabel() {
- switch (this.behaviorPref) {
- case Ci.nsICookieService.BEHAVIOR_ACCEPT:
- return "nocookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
- return "allthirdpartycookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_REJECT:
- return "allcookiesblocked";
- case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
- return "cookiesfromunvisitedsitesblocked";
- default:
- Cu.reportError(
- `Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`
- );
- // fall through
- case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
- return "cookierestrictions";
- case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN:
- return "cookierestrictionsforeignpartitioned";
- }
- },
-
- updateCategoryLabel() {
- let label;
- switch (this.behaviorPref) {
- case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.cookies.blocking3rdParty.label"
- : null;
- break;
- case Ci.nsICookieService.BEHAVIOR_REJECT:
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.cookies.blockingAll.label"
- : null;
- break;
- case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.cookies.blockingUnvisited.label"
- : null;
- break;
- case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
- label = gProtectionsHandler.showBlockedLabels
- ? "contentBlocking.cookies.blockingTrackers.label"
- : null;
- break;
- default:
- Cu.reportError(
- `Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`
- );
- // fall through
- case Ci.nsICookieService.BEHAVIOR_ACCEPT:
- label = gProtectionsHandler.showAllowedLabels
- ? "contentBlocking.cookies.allowed.label"
- : null;
- break;
- }
- this.categoryLabel.textContent = label
- ? gNavigatorBundle.getString(label)
- : "";
- },
-
- init() {
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "behaviorPref",
- this.PREF_ENABLED,
- Ci.nsICookieService.BEHAVIOR_ACCEPT,
- this.updateCategoryLabel.bind(this)
- );
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "reportBreakageEnabled",
- this.PREF_REPORT_BREAKAGE_ENABLED,
- false
- );
- this.updateCategoryLabel();
- },
-
- get enabled() {
- return this.PREF_ENABLED_VALUES.includes(this.behaviorPref);
- },
-
- isBlocking(state) {
- return (
- (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER) != 0 ||
- (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_ALL) != 0 ||
- (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_BY_PERMISSION) !=
- 0 ||
- (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_FOREIGN) != 0
- );
- },
-
- isDetected(state) {
- return (state & Ci.nsIWebProgressListener.STATE_COOKIES_LOADED) != 0;
- },
-
- async updateSubView() {
- let contentBlockingLog = await gBrowser.selectedBrowser.getContentBlockingLog();
- contentBlockingLog = JSON.parse(contentBlockingLog);
-
- let categories = this._processContentBlockingLog(contentBlockingLog);
-
- this.subViewList.textContent = "";
-
- for (let category of ["firstParty", "trackers", "thirdParty"]) {
- let box = document.createXULElement("vbox");
- let label = document.createXULElement("label");
- label.className = "identity-popup-cookiesView-list-header";
- label.textContent = gNavigatorBundle.getString(
- `contentBlocking.cookiesView.${category}.label`
- );
- box.appendChild(label);
-
- for (let info of categories[category]) {
- box.appendChild(this._createListItem(info));
- }
-
- // If the category is empty, add a label noting that to the user.
- if (categories[category].length == 0) {
- let emptyLabel = document.createXULElement("label");
- emptyLabel.classList.add("identity-popup-content-blocking-empty-label");
- emptyLabel.textContent = gNavigatorBundle.getString(
- `contentBlocking.cookiesView.${category}.empty.label`
- );
- box.appendChild(emptyLabel);
- }
-
- this.subViewList.appendChild(box);
- }
- },
-
- _hasException(origin) {
- for (let perm of Services.perms.getAllForPrincipal(
- gBrowser.contentPrincipal
- )) {
- if (
- perm.type == "3rdPartyStorage^" + origin ||
- perm.type.startsWith("3rdPartyStorage^" + origin + "^")
- ) {
- return true;
- }
- }
-
- let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
- origin
- );
- // Cookie exceptions get "inherited" from parent- to sub-domain, so we need to
- // make sure to include parent domains in the permission check for "cookies".
- return (
- Services.perms.testPermissionFromPrincipal(principal, "cookie") !=
- Services.perms.UNKNOWN_ACTION
- );
- },
-
- _clearException(origin) {
- for (let perm of Services.perms.getAllForPrincipal(
- gBrowser.contentPrincipal
- )) {
- if (
- perm.type == "3rdPartyStorage^" + origin ||
- perm.type.startsWith("3rdPartyStorage^" + origin + "^")
- ) {
- Services.perms.removePermission(perm);
- }
- }
-
- // OAs don't matter here, so we can just use the hostname.
- let host = Services.io.newURI(origin).host;
-
- // Cookie exceptions get "inherited" from parent- to sub-domain, so we need to
- // clear any cookie permissions from parent domains as well.
- for (let perm of Services.perms.enumerator) {
- if (
- perm.type == "cookie" &&
- Services.eTLD.hasRootDomain(host, perm.principal.URI.host)
- ) {
- Services.perms.removePermission(perm);
- }
- }
- },
-
- // Transforms and filters cookie entries in the content blocking log
- // so that we can categorize and display them in the UI.
- _processContentBlockingLog(log) {
- let newLog = {
- firstParty: [],
- trackers: [],
- thirdParty: [],
- };
-
- let firstPartyDomain = null;
- try {
- firstPartyDomain = Services.eTLD.getBaseDomain(gBrowser.currentURI);
- } catch (e) {
- // There are nasty edge cases here where someone is trying to set a cookie
- // on a public suffix or an IP address. Just categorize those as third party...
- if (
- e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS &&
- e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
- ) {
- throw e;
- }
- }
-
- for (let [origin, actions] of Object.entries(log)) {
- if (!origin.startsWith("http")) {
- continue;
- }
-
- let info = {
- origin,
- isAllowed: true,
- hasException: this._hasException(origin),
- };
- let hasCookie = false;
- let isTracker = false;
-
- // Extract information from the states entries in the content blocking log.
- // Each state will contain a single state flag from nsIWebProgressListener.
- // Note that we are using the same helper functions that are applied to the
- // bit map passed to onSecurityChange (which contains multiple states), thus
- // not checking exact equality, just presence of bits.
- for (let [state, blocked] of actions) {
- if (this.isDetected(state)) {
- hasCookie = true;
- }
- if (TrackingProtection.isAllowing(state)) {
- isTracker = true;
- }
- // blocked tells us whether the resource was actually blocked
- // (which it may not be in case of an exception).
- if (this.isBlocking(state)) {
- info.isAllowed = !blocked;
- }
- }
-
- if (!hasCookie) {
- continue;
- }
-
- let isFirstParty = false;
- try {
- let uri = Services.io.newURI(origin);
- isFirstParty = Services.eTLD.getBaseDomain(uri) == firstPartyDomain;
- } catch (e) {
- if (
- e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS &&
- e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
- ) {
- throw e;
- }
- }
-
- if (isFirstParty) {
- newLog.firstParty.push(info);
- } else if (isTracker) {
- newLog.trackers.push(info);
- } else {
- newLog.thirdParty.push(info);
- }
- }
-
- return newLog;
- },
-
- _createListItem({ origin, isAllowed, hasException }) {
- let listItem = document.createXULElement("hbox");
- listItem.className = "identity-popup-content-blocking-list-item";
- listItem.classList.toggle("allowed", isAllowed);
- // Repeat the origin in the tooltip in case it's too long
- // and overflows in our panel.
- listItem.tooltipText = origin;
-
- let image = document.createXULElement("image");
- image.className = "identity-popup-cookiesView-icon";
- image.classList.toggle("allowed", isAllowed);
- listItem.append(image);
-
- let label = document.createXULElement("label");
- label.value = origin;
- label.className = "identity-popup-content-blocking-list-host-label";
- label.setAttribute("crop", "end");
- listItem.append(label);
-
- let stateLabel;
- if (isAllowed && hasException) {
- stateLabel = document.createXULElement("label");
- stateLabel.value = this.strings.subViewAllowed;
- stateLabel.className = "identity-popup-content-blocking-list-state-label";
- listItem.append(stateLabel);
- } else if (!isAllowed) {
- stateLabel = document.createXULElement("label");
- stateLabel.value = this.strings.subViewBlocked;
- stateLabel.className = "identity-popup-content-blocking-list-state-label";
- listItem.append(stateLabel);
- }
-
- if (hasException) {
- let removeException = document.createXULElement("button");
- removeException.className = "identity-popup-permission-remove-button";
- removeException.tooltipText = gNavigatorBundle.getFormattedString(
- "contentBlocking.cookiesView.removeButton.tooltip",
- [origin]
- );
- removeException.addEventListener("click", () => {
- this._clearException(origin);
- // Just flip the display based on what state we had previously.
- stateLabel.value = isAllowed
- ? this.strings.subViewBlocked
- : this.strings.subViewAllowed;
- listItem.classList.toggle("allowed", !isAllowed);
- image.classList.toggle("allowed", !isAllowed);
- removeException.hidden = true;
- });
- listItem.append(removeException);
- }
-
- return listItem;
- },
-};
-
/**
* Utility object to handle manipulations of the protections indicators in the UI
*/
var gProtectionsHandler = {
- PREF_ANIMATIONS_ENABLED: "toolkit.cosmeticAnimations.enabled",
- PREF_REPORT_BREAKAGE_ENABLED:
- "browser.contentblocking.reportBreakage.enabled",
- PREF_REPORT_BREAKAGE_URL: "browser.contentblocking.reportBreakage.url",
- PREF_CB_CATEGORY: "browser.contentblocking.category",
- PREF_SHOW_ALLOWED_LABELS:
- "browser.contentblocking.control-center.ui.showAllowedLabels",
- PREF_SHOW_BLOCKED_LABELS:
- "browser.contentblocking.control-center.ui.showBlockedLabels",
-
// smart getters
get _protectionsPopup() {
delete this._protectionsPopup;
@@ -925,22 +15,6 @@ var gProtectionsHandler = {
"protections-popup"
));
},
- get iconBox() {
- delete this.iconBox;
- return (this.iconBox = document.getElementById(
- "tracking-protection-icon-box"
- ));
- },
- get animatedIcon() {
- delete this.animatedIcon;
- return (this.animatedIcon = document.getElementById(
- "tracking-protection-icon-animatable-image"
- ));
- },
- get appMenuLabel() {
- delete this.appMenuLabel;
- return (this.appMenuLabel = document.getElementById("appMenu-tp-label"));
- },
get _protectionsIconBox() {
delete this._protectionsIconBox;
return (this._protectionsIconBox = document.getElementById(
@@ -977,12 +51,6 @@ var gProtectionsHandler = {
"protections-popup-tp-switch"
));
},
- get _breakageLink() {
- delete this._breakageLink;
- return (this._breakageLink = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
- ));
- },
get _protectionPopupSettingsButton() {
delete this._protectionPopupSettingsButton;
return (this._protectionPopupSettingsButton = document.getElementById(
@@ -1019,224 +87,15 @@ var gProtectionsHandler = {
"protections-popup-sendReportView-collection-url"
));
},
-
- strings: {
- get appMenuTitle() {
- delete this.appMenuTitle;
- return (this.appMenuTitle = gNavigatorBundle.getString(
- "contentBlocking.title"
- ));
- },
-
- get appMenuTooltip() {
- delete this.appMenuTooltip;
- if (AppConstants.platform == "win") {
- return (this.appMenuTooltip = gNavigatorBundle.getString(
- "contentBlocking.tooltipWin"
- ));
- }
- return (this.appMenuTooltip = gNavigatorBundle.getString(
- "contentBlocking.tooltipOther"
- ));
- },
-
- get activeTooltipText() {
- delete this.activeTooltipText;
- return (this.activeTooltipText = gNavigatorBundle.getString(
- "trackingProtection.icon.activeTooltip"
- ));
- },
-
- get disabledTooltipText() {
- delete this.disabledTooltipText;
- return (this.disabledTooltipText = gNavigatorBundle.getString(
- "trackingProtection.icon.disabledTooltip"
- ));
- },
- },
-
- // A list of blockers that will be displayed in the categories list
- // when blockable content is detected. A blocker must be an object
- // with at least the following two properties:
- // - enabled: Whether the blocker is currently turned on.
- // - isDetected(state): Given a content blocking state, whether the blocker has
- // either allowed or blocked elements.
- // - categoryItem: The DOM item that represents the entry in the category list.
- //
- // It may also contain an init() and uninit() function, which will be called
- // on gProtectionsHandler.init() and gProtectionsHandler.uninit().
- blockers: [
- TrackingProtection,
- ThirdPartyCookies,
- Fingerprinting,
- Cryptomining,
- ],
-
- init() {
- this.animatedIcon.addEventListener("animationend", () =>
- this.iconBox.removeAttribute("animate")
- );
-
- this.updateAnimationsEnabled = () => {
- this.iconBox.toggleAttribute(
- "animationsenabled",
- Services.prefs.getBoolPref(this.PREF_ANIMATIONS_ENABLED, false)
- );
- };
-
+ get _protectionsPopupToastTimeout() {
+ delete this._protectionsPopupToastTimeout;
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_protectionsPopupToastTimeout",
"browser.protections_panel.toast.timeout",
5000
);
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "showBlockedLabels",
- this.PREF_SHOW_BLOCKED_LABELS,
- false,
- () => {
- for (let blocker of this.blockers) {
- blocker.updateCategoryLabel();
- }
- }
- );
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "showAllowedLabels",
- this.PREF_SHOW_ALLOWED_LABELS,
- false,
- () => {
- for (let blocker of this.blockers) {
- blocker.updateCategoryLabel();
- }
- }
- );
- XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "reportBreakageEnabled",
- this.PREF_REPORT_BREAKAGE_ENABLED,
- false
- );
-
- for (let blocker of this.blockers) {
- if (blocker.init) {
- blocker.init();
- }
- }
-
- this.updateAnimationsEnabled();
-
- Services.prefs.addObserver(
- this.PREF_ANIMATIONS_ENABLED,
- this.updateAnimationsEnabled
- );
-
- let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
- gProtectionsHandler._protectionsPopupSendReportLearnMore.href =
- baseURL + "blocking-breakage";
-
- this.appMenuLabel.setAttribute("value", this.strings.appMenuTitle);
- this.appMenuLabel.setAttribute("tooltiptext", this.strings.appMenuTooltip);
-
- this.updateCBCategoryLabel = this.updateCBCategoryLabel.bind(this);
- this.updateCBCategoryLabel();
- Services.prefs.addObserver(
- this.PREF_CB_CATEGORY,
- this.updateCBCategoryLabel
- );
- },
-
- uninit() {
- for (let blocker of this.blockers) {
- if (blocker.uninit) {
- blocker.uninit();
- }
- }
-
- Services.prefs.removeObserver(
- this.PREF_ANIMATIONS_ENABLED,
- this.updateAnimationsEnabled
- );
- Services.prefs.removeObserver(
- this.PREF_CB_CATEGORY,
- this.updateCBCategoryLabel
- );
- },
-
- updateCBCategoryLabel() {
- if (!Services.prefs.prefHasUserValue(this.PREF_CB_CATEGORY)) {
- // Fallback to not setting a label, it's preferable to not set a label than to set an incorrect one.
- return;
- }
- let button = document.getElementById(
- "tracking-protection-preferences-button"
- );
- let appMenuCategoryLabel = document.getElementById("appMenu-tp-category");
- let label;
- let category = Services.prefs.getStringPref(this.PREF_CB_CATEGORY);
- switch (category) {
- case "standard":
- label = gNavigatorBundle.getString("contentBlocking.category.standard");
- break;
- case "strict":
- label = gNavigatorBundle.getString("contentBlocking.category.strict");
- break;
- case "custom":
- label = gNavigatorBundle.getString("contentBlocking.category.custom");
- break;
- }
- appMenuCategoryLabel.value = label;
- button.label = label;
- },
-
- openPreferences(origin) {
- openPreferences("privacy-trackingprotection", { origin });
- },
-
- async showTrackersSubview() {
- await TrackingProtection.updateSubView();
- this._protectionsPopupMultiView.showSubView("identity-popup-trackersView");
- },
-
- async showCookiesSubview() {
- await ThirdPartyCookies.updateSubView();
- this._protectionsPopupMultiView.showSubView("identity-popup-cookiesView");
- },
-
- async showFingerprintersSubview() {
- await Fingerprinting.updateSubView();
- this._protectionsPopupMultiView.showSubView(
- "identity-popup-fingerprintersView"
- );
- },
-
- async showCryptominersSubview() {
- await Cryptomining.updateSubView();
- this._protectionsPopupMultiView.showSubView(
- "identity-popup-cryptominersView"
- );
- },
-
- shieldHistogramAdd(value) {
- if (PrivateBrowsingUtils.isWindowPrivate(window)) {
- return;
- }
- Services.telemetry
- .getHistogramById("TRACKING_PROTECTION_SHIELD")
- .add(value);
- },
-
- cryptominersHistogramAdd(value) {
- Services.telemetry
- .getHistogramById("CRYPTOMINERS_BLOCKED_COUNT")
- .add(value);
- },
-
- fingerprintersHistogramAdd(value) {
- Services.telemetry
- .getHistogramById("FINGERPRINTERS_BLOCKED_COUNT")
- .add(value);
+ return this._protectionsPopupToastTimeout;
},
handleProtectionsButtonEvent(event) {
@@ -1277,142 +136,26 @@ var gProtectionsHandler = {
}
},
- // This triggers from top level location changes.
onLocationChange() {
- if (this._showToastAfterRefresh) {
- this._showToastAfterRefresh = false;
-
- // We only display the toast if we're still on the same page.
- if (
- this._previousURI == gBrowser.currentURI.spec &&
- this._previousOuterWindowID == gBrowser.selectedBrowser.outerWindowID
- ) {
- this.showProtectionsPopup({
- toast: true,
- });
- }
- }
-
- // Reset blocking and exception status so that we can send telemetry
- this.hadShieldState = false;
-
- // Don't deal with about:, file: etc.
- if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
+ if (!this._showToastAfterRefresh) {
return;
}
- // Check whether the user has added an exception for this site.
- let hasException = ContentBlockingAllowList.includes(
- gBrowser.selectedBrowser
- );
+ this._showToastAfterRefresh = false;
- this._protectionsPopup.toggleAttribute("hasException", hasException);
- this.iconBox.toggleAttribute("hasException", hasException);
-
- // Add to telemetry per page load as a baseline measurement.
- this.fingerprintersHistogramAdd("pageLoad");
- this.cryptominersHistogramAdd("pageLoad");
- this.shieldHistogramAdd(0);
- },
-
- onContentBlockingEvent(event, webProgress, isSimulated) {
- let previousState = gBrowser.securityUI.contentBlockingEvent;
-
- // Don't deal with about:, file: etc.
- if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
- this.iconBox.removeAttribute("animate");
- this.iconBox.removeAttribute("active");
- this.iconBox.removeAttribute("hasException");
+ // We only display the toast if we're still on the same page.
+ if (
+ this._previousURI != gBrowser.currentURI.spec ||
+ this._previousOuterWindowID != gBrowser.selectedBrowser.outerWindowID
+ ) {
return;
}
- let anyDetected = false;
- let anyBlocking = false;
-
- for (let blocker of this.blockers) {
- // Store data on whether the blocker is activated in the current document for
- // reporting it using the "report breakage" dialog. Under normal circumstances this
- // dialog should only be able to open in the currently selected tab and onSecurityChange
- // runs on tab switch, so we can avoid associating the data with the document directly.
- blocker.activated = blocker.isBlocking(event);
- blocker.categoryItem.classList.toggle("blocked", blocker.enabled);
- let detected = blocker.isDetected(event);
- blocker.categoryItem.hidden = !detected;
- anyDetected = anyDetected || detected;
- anyBlocking = anyBlocking || blocker.activated;
- }
-
- // Check whether the user has added an exception for this site.
- let hasException = ContentBlockingAllowList.includes(
- gBrowser.selectedBrowser
- );
-
- // Reset the animation in case the user is switching tabs or if no blockers were detected
- // (this is most likely happening because the user navigated on to a different site). This
- // allows us to play it from the start without choppiness next time.
- if (isSimulated || !anyBlocking) {
- this.iconBox.removeAttribute("animate");
- // Only play the animation when the shield is not already shown on the page (the visibility
- // of the shield based on this onSecurityChange be determined afterwards).
- } else if (anyBlocking && !this.iconBox.hasAttribute("active")) {
- this.iconBox.setAttribute("animate", "true");
- }
-
- // We consider the shield state "active" when some kind of blocking activity
- // occurs on the page. Note that merely allowing the loading of content that
- // we could have blocked does not trigger the appearance of the shield.
- // This state will be overriden later if there's an exception set for this site.
- this._protectionsPopup.toggleAttribute("detected", anyDetected);
- this._protectionsPopup.toggleAttribute("blocking", anyBlocking);
- this._protectionsPopup.toggleAttribute("hasException", hasException);
-
- this.iconBox.toggleAttribute("active", anyBlocking);
- this.iconBox.toggleAttribute("hasException", hasException);
-
- if (hasException) {
- this.iconBox.setAttribute(
- "tooltiptext",
- this.strings.disabledTooltipText
- );
- if (!this.hadShieldState && !isSimulated) {
- this.hadShieldState = true;
- this.shieldHistogramAdd(1);
- }
- } else if (anyBlocking) {
- this.iconBox.setAttribute("tooltiptext", this.strings.activeTooltipText);
- if (!this.hadShieldState && !isSimulated) {
- this.hadShieldState = true;
- this.shieldHistogramAdd(2);
- }
- } else {
- this.iconBox.removeAttribute("tooltiptext");
- }
-
- // We report up to one instance of fingerprinting and cryptomining
- // blocking and/or allowing per page load.
- let fingerprintingBlocking =
- Fingerprinting.isBlocking(event) &&
- !Fingerprinting.isBlocking(previousState);
- let fingerprintingAllowing =
- Fingerprinting.isAllowing(event) &&
- !Fingerprinting.isAllowing(previousState);
- let cryptominingBlocking =
- Cryptomining.isBlocking(event) && !Cryptomining.isBlocking(previousState);
- let cryptominingAllowing =
- Cryptomining.isAllowing(event) && !Cryptomining.isAllowing(previousState);
-
- if (fingerprintingBlocking) {
- this.fingerprintersHistogramAdd("blocked");
- } else if (fingerprintingAllowing) {
- this.fingerprintersHistogramAdd("allowed");
- }
-
- if (cryptominingBlocking) {
- this.cryptominersHistogramAdd("blocked");
- } else if (cryptominingAllowing) {
- this.cryptominersHistogramAdd("allowed");
- }
+ this.showProtectionsPopup({
+ toast: true,
+ });
},
+
handleEvent(event) {
let elem = document.activeElement;
let position = elem.compareDocumentPosition(this._protectionsPopup);
@@ -1460,18 +203,6 @@ var gProtectionsHandler = {
this.setTrackersBlockedCounter(244051);
},
- disableForCurrentPage() {
- ContentBlockingAllowList.add(gBrowser.selectedBrowser);
- PanelMultiView.hidePopup(this._protectionsPopup);
- BrowserReload();
- },
-
- enableForCurrentPage() {
- ContentBlockingAllowList.remove(gBrowser.selectedBrowser);
- PanelMultiView.hidePopup(this._protectionsPopup);
- BrowserReload();
- },
-
async onTPSwitchCommand(event) {
// When the switch is clicked, we wait 500ms and then disable/enable
// protections, causing the page to refresh, and close the popup.
@@ -1505,11 +236,14 @@ var gProtectionsHandler = {
await new Promise(resolve => setTimeout(resolve, 500));
if (newExceptionState) {
- this.disableForCurrentPage();
+ ContentBlocking.disableForCurrentPage();
+ gIdentityHandler.recordClick("unblock");
} else {
- this.enableForCurrentPage();
+ ContentBlocking.enableForCurrentPage();
+ gIdentityHandler.recordClick("block");
}
+ PanelMultiView.hidePopup(this._protectionsPopup);
delete this._TPSwitchCommanding;
},
@@ -1565,10 +299,6 @@ var gProtectionsHandler = {
);
}
- // Adjust "site not working?" visibility based on whether we're
- // blocking something or not.
- gProtectionsHandler.toggleBreakageLink();
-
// Now open the popup, anchored off the primary chrome element
PanelMultiView.openPopup(
this._protectionsPopup,
@@ -1600,117 +330,15 @@ var gProtectionsHandler = {
);
},
- toggleBreakageLink() {
- // For release (due to the large volume) we only want to receive reports
- // for breakage that is directly related to third party cookie blocking.
- if (
- this.reportBreakageEnabled ||
- (ThirdPartyCookies.reportBreakageEnabled &&
- ThirdPartyCookies.activated &&
- !TrackingProtection.activated)
- ) {
- this._breakageLink.removeAttribute("hidden");
- } else {
- this._breakageLink.setAttribute("hidden", "true");
- }
- },
-
- submitBreakageReport(uri) {
- let reportEndpoint = Services.prefs.getStringPref(
- this.PREF_REPORT_BREAKAGE_URL
- );
- if (!reportEndpoint) {
- return;
- }
-
- let commentsTextarea = document.getElementById(
- "protections-popup-sendReportView-collection-comments"
- );
-
- let formData = new FormData();
- formData.set("title", uri.host);
-
- // Leave the ? at the end of the URL to signify that this URL had its query stripped.
- let urlWithoutQuery = uri.asciiSpec.replace(uri.query, "");
- let body = `Full URL: ${urlWithoutQuery}\n`;
- body += `userAgent: ${navigator.userAgent}\n`;
-
- body += "\n**Preferences**\n";
- body += `${
- TrackingProtection.PREF_ENABLED_GLOBALLY
- }: ${Services.prefs.getBoolPref(
- TrackingProtection.PREF_ENABLED_GLOBALLY
- )}\n`;
- body += `${
- TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS
- }: ${Services.prefs.getBoolPref(
- TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS
- )}\n`;
- body += `urlclassifier.trackingTable: ${Services.prefs.getStringPref(
- "urlclassifier.trackingTable"
- )}\n`;
- body += `network.http.referer.defaultPolicy: ${Services.prefs.getIntPref(
- "network.http.referer.defaultPolicy"
- )}\n`;
- body += `network.http.referer.defaultPolicy.pbmode: ${Services.prefs.getIntPref(
- "network.http.referer.defaultPolicy.pbmode"
- )}\n`;
- body += `${ThirdPartyCookies.PREF_ENABLED}: ${Services.prefs.getIntPref(
- ThirdPartyCookies.PREF_ENABLED
- )}\n`;
- body += `network.cookie.lifetimePolicy: ${Services.prefs.getIntPref(
- "network.cookie.lifetimePolicy"
- )}\n`;
- body += `privacy.annotate_channels.strict_list.enabled: ${Services.prefs.getBoolPref(
- "privacy.annotate_channels.strict_list.enabled"
- )}\n`;
- body += `privacy.restrict3rdpartystorage.expiration: ${Services.prefs.getIntPref(
- "privacy.restrict3rdpartystorage.expiration"
- )}\n`;
- body += `${Fingerprinting.PREF_ENABLED}: ${Services.prefs.getBoolPref(
- Fingerprinting.PREF_ENABLED
- )}\n`;
- body += `${Cryptomining.PREF_ENABLED}: ${Services.prefs.getBoolPref(
- Cryptomining.PREF_ENABLED
- )}\n`;
-
- body += "\n**Comments**\n" + commentsTextarea.value;
-
- formData.set("body", body);
-
- let activatedBlockers = [];
- for (let blocker of this.blockers) {
- if (blocker.activated) {
- activatedBlockers.push(blocker.reportBreakageLabel);
- }
- }
-
- if (activatedBlockers.length) {
- formData.set("labels", activatedBlockers.join(","));
- }
-
- fetch(reportEndpoint, {
- method: "POST",
- credentials: "omit",
- body: formData,
- })
- .then(function(response) {
- if (!response.ok) {
- Cu.reportError(
- `Content Blocking report to ${reportEndpoint} failed with status ${
- response.status
- }`
- );
- } else {
- // Clear the textarea value when the report is submitted
- commentsTextarea.value = "";
- }
- })
- .catch(Cu.reportError);
- },
-
onSendReportClicked() {
this._protectionsPopup.hidePopup();
- this.submitBreakageReport(this.reportURI);
+ let comments = document.getElementById(
+ "protections-popup-sendReportView-collection-comments"
+ );
+ ContentBlocking.submitBreakageReport(this.reportURI, comments);
},
};
+
+let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
+gProtectionsHandler._protectionsPopupSendReportLearnMore.href =
+ baseURL + "blocking-breakage";
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index fd76b329fa47..2ca91f663e1e 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1943,7 +1943,7 @@ var gBrowserInit = {
BookmarkingUI.init();
BrowserSearch.delayedStartupInit();
AutoShowBookmarksToolbar.init();
- gProtectionsHandler.init();
+ ContentBlocking.init();
let safeMode = document.getElementById("helpSafeMode");
if (Services.appinfo.inSafeMode) {
@@ -2423,7 +2423,7 @@ var gBrowserInit = {
Services.prefs.removeObserver(ctrlTab.prefName, ctrlTab);
ctrlTab.uninit();
gBrowserThumbnails.uninit();
- gProtectionsHandler.uninit();
+ ContentBlocking.uninit();
FullZoom.destroy();
Services.obs.removeObserver(gIdentityHandler, "perm-changed");
@@ -5739,7 +5739,7 @@ var XULBrowserWindow = {
);
}
- gProtectionsHandler.onContentBlockingEvent(
+ ContentBlocking.onContentBlockingEvent(
this._event,
aWebProgress,
aIsSimulated
@@ -6366,6 +6366,8 @@ var TabsProgressListener = {
gBrowser.getNotificationBox(aBrowser).removeTransientNotifications();
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
+
+ ContentBlocking.onLocationChange();
},
onLinkIconAvailable(browser, dataURI, iconURI) {
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index 11b0553fa95b..2f028021baf6 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -81,6 +81,7 @@
/* eslint-env mozilla/browser-window */
Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/browser-captivePortal.js", this);
+ Services.scriptloader.loadSubScript("chrome://browser/content/browser-contentblocking.js", this);
if (AppConstants.MOZ_DATA_REPORTING) {
Services.scriptloader.loadSubScript("chrome://browser/content/browser-data-submission-info-bar.js", this);
}
diff --git a/browser/base/content/test/siteIdentity/browser.ini b/browser/base/content/test/siteIdentity/browser.ini
index e405118935e9..da2c04e1b299 100644
--- a/browser/base/content/test/siteIdentity/browser.ini
+++ b/browser/base/content/test/siteIdentity/browser.ini
@@ -52,7 +52,6 @@ support-files = ../permissions/permissions.html
[browser_identityPopup_clearSiteData.js]
[browser_identityPopup_custom_roots.js]
[browser_identityPopup_focus.js]
-[browser_identityPopup_telemetry.js]
[browser_insecureLoginForms.js]
support-files =
insecure_opener.html
diff --git a/browser/base/content/test/siteIdentity/browser_identityPopup_telemetry.js b/browser/base/content/test/siteIdentity/browser_identityPopup_telemetry.js
deleted file mode 100644
index c02ff1b4238e..000000000000
--- a/browser/base/content/test/siteIdentity/browser_identityPopup_telemetry.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const BENIGN_PAGE =
- "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
-
-/**
- * Enable local telemetry recording for the duration of the tests.
- */
-var oldCanRecord = Services.telemetry.canRecordExtended;
-Services.telemetry.canRecordExtended = true;
-registerCleanupFunction(function() {
- Services.telemetry.canRecordExtended = oldCanRecord;
-});
-
-add_task(async function testIdentityPopupEvents() {
- let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
-
- await promiseTabLoadEvent(tab, BENIGN_PAGE);
-
- Services.telemetry.clearEvents();
-
- let shown = BrowserTestUtils.waitForEvent(
- gIdentityHandler._identityPopup,
- "popupshown"
- );
- EventUtils.synthesizeMouseAtCenter(gIdentityHandler._identityBox, {});
- await shown;
-
- let events = Services.telemetry.snapshotEvents(
- Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
- true
- ).parent;
- let openEvents = events.filter(
- e =>
- e[1] == "security.ui.identitypopup" &&
- e[2] == "open" &&
- e[3] == "identity_popup"
- );
- is(openEvents.length, 1, "recorded telemetry for opening the identity popup");
-
- gBrowser.removeCurrentTab();
-});
diff --git a/browser/base/content/test/siteProtections/browser_protections_UI.js b/browser/base/content/test/siteProtections/browser_protections_UI.js
index 1232e6dc11c5..d088594687bf 100644
--- a/browser/base/content/test/siteProtections/browser_protections_UI.js
+++ b/browser/base/content/test/siteProtections/browser_protections_UI.js
@@ -3,12 +3,6 @@
/* Basic UI tests for the protections panel */
-ChromeUtils.defineModuleGetter(
- this,
- "ContentBlockingAllowList",
- "resource://gre/modules/ContentBlockingAllowList.jsm"
-);
-
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
@@ -60,7 +54,43 @@ add_task(async function testToggleSwitch() {
!gProtectionsHandler._protectionsPopupTPSwitch.hasAttribute("enabled"),
"TP Switch should be disabled"
);
- ContentBlockingAllowList.remove(tab.linkedBrowser);
+ Services.perms.remove(
+ ContentBlocking._baseURIForChannelClassifier,
+ "trackingprotection"
+ );
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function testSiteNotWorking() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "https://example.com"
+ );
+ await openProtectionsPanel();
+ let viewShownPromise = BrowserTestUtils.waitForEvent(
+ gProtectionsHandler._protectionsPopupMultiView,
+ "ViewShown"
+ );
+ document.getElementById("protections-popup-tp-switch-breakage-link").click();
+ let event = await viewShownPromise;
+ is(
+ event.originalTarget.id,
+ "protections-popup-siteNotWorkingView",
+ "Site Not Working? view should be shown"
+ );
+ viewShownPromise = BrowserTestUtils.waitForEvent(
+ gProtectionsHandler._protectionsPopupMultiView,
+ "ViewShown"
+ );
+ document
+ .getElementById("protections-popup-siteNotWorkingView-sendReport")
+ .click();
+ event = await viewShownPromise;
+ is(
+ event.originalTarget.id,
+ "protections-popup-sendReportView",
+ "Send Report view should be shown"
+ );
BrowserTestUtils.removeTab(tab);
});
@@ -254,6 +284,9 @@ add_task(async function testToggleSwitchFlow() {
await popuphiddenPromise;
// Clean up the TP state.
- ContentBlockingAllowList.remove(tab.linkedBrowser);
+ Services.perms.remove(
+ ContentBlocking._baseURIForChannelClassifier,
+ "trackingprotection"
+ );
BrowserTestUtils.removeTab(tab);
});
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_animation_2.js b/browser/base/content/test/trackingUI/browser_trackingUI_animation_2.js
index 8b638015fa4e..a0c37042c391 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_animation_2.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_animation_2.js
@@ -34,13 +34,10 @@ async function testTrackingProtectionAnimation(tabbrowser) {
tabbrowser,
BENIGN_PAGE
);
- let gProtectionsHandler = tabbrowser.ownerGlobal.gProtectionsHandler;
+ let ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
- ok(!gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox not active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "iconBox not active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Load a test page containing tracking elements");
let trackingTab = await BrowserTestUtils.openNewForegroundTab(
@@ -48,10 +45,10 @@ async function testTrackingProtectionAnimation(tabbrowser) {
TRACKING_PAGE
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(gProtectionsHandler.iconBox.hasAttribute("animate"), "iconBox animating");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
await BrowserTestUtils.waitForEvent(
- gProtectionsHandler.animatedIcon,
+ ContentBlocking.animatedIcon,
"animationend"
);
@@ -61,10 +58,10 @@ async function testTrackingProtectionAnimation(tabbrowser) {
COOKIE_PAGE
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(gProtectionsHandler.iconBox.hasAttribute("animate"), "iconBox animating");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
await BrowserTestUtils.waitForEvent(
- gProtectionsHandler.animatedIcon,
+ ContentBlocking.animatedIcon,
"animationend"
);
@@ -73,33 +70,24 @@ async function testTrackingProtectionAnimation(tabbrowser) {
tabbrowser.selectedTab = benignTab;
await securityChanged;
- ok(!gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox not active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "iconBox not active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Switch from benign -> tracking tab");
securityChanged = waitForSecurityChange(1, tabbrowser.ownerGlobal);
tabbrowser.selectedTab = trackingTab;
await securityChanged;
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Switch from tracking -> tracking cookies tab");
securityChanged = waitForSecurityChange(1, tabbrowser.ownerGlobal);
tabbrowser.selectedTab = trackingCookiesTab;
await securityChanged;
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Reload tracking cookies tab");
securityChanged = waitForSecurityChange(1, tabbrowser.ownerGlobal);
@@ -110,10 +98,10 @@ async function testTrackingProtectionAnimation(tabbrowser) {
tabbrowser.reload();
await Promise.all([securityChanged, contentBlockingEvent]);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(gProtectionsHandler.iconBox.hasAttribute("animate"), "iconBox animating");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
await BrowserTestUtils.waitForEvent(
- gProtectionsHandler.animatedIcon,
+ ContentBlocking.animatedIcon,
"animationend"
);
@@ -124,10 +112,10 @@ async function testTrackingProtectionAnimation(tabbrowser) {
tabbrowser.reload();
await Promise.all([securityChanged, contentBlockingEvent]);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(gProtectionsHandler.iconBox.hasAttribute("animate"), "iconBox animating");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
await BrowserTestUtils.waitForEvent(
- gProtectionsHandler.animatedIcon,
+ ContentBlocking.animatedIcon,
"animationend"
);
@@ -140,11 +128,8 @@ async function testTrackingProtectionAnimation(tabbrowser) {
let result = await Promise.race([securityChanged, timeoutPromise]);
is(result, undefined, "No securityChange events should be received");
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Inject tracking element inside tracking tab");
securityChanged = waitForSecurityChange(1, tabbrowser.ownerGlobal);
@@ -155,11 +140,8 @@ async function testTrackingProtectionAnimation(tabbrowser) {
result = await Promise.race([securityChanged, timeoutPromise]);
is(result, undefined, "No securityChange events should be received");
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
tabbrowser.selectedTab = trackingCookiesTab;
@@ -172,11 +154,8 @@ async function testTrackingProtectionAnimation(tabbrowser) {
result = await Promise.race([securityChanged, timeoutPromise]);
is(result, undefined, "No securityChange events should be received");
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Inject tracking element inside tracking cookies tab");
securityChanged = waitForSecurityChange(1, tabbrowser.ownerGlobal);
@@ -187,11 +166,8 @@ async function testTrackingProtectionAnimation(tabbrowser) {
result = await Promise.race([securityChanged, timeoutPromise]);
is(result, undefined, "No securityChange events should be received");
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "iconBox active");
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("animate"),
- "iconBox not animating"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
+ ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
while (tabbrowser.tabs.length > 1) {
tabbrowser.removeCurrentTab();
@@ -201,11 +177,8 @@ async function testTrackingProtectionAnimation(tabbrowser) {
add_task(async function testNormalBrowsing() {
await UrlClassifierTestUtils.addTestTrackers();
- let gProtectionsHandler = gBrowser.ownerGlobal.gProtectionsHandler;
- ok(
- gProtectionsHandler,
- "gProtectionsHandler is attached to the browser window"
- );
+ let ContentBlocking = gBrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the browser window");
let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
let ThirdPartyCookies = gBrowser.ownerGlobal.ThirdPartyCookies;
@@ -231,11 +204,8 @@ add_task(async function testPrivateBrowsing() {
});
let tabbrowser = privateWin.gBrowser;
- let gProtectionsHandler = tabbrowser.ownerGlobal.gProtectionsHandler;
- ok(
- gProtectionsHandler,
- "gProtectionsHandler is attached to the private window"
- );
+ let ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the private window");
let TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
let ThirdPartyCookies = tabbrowser.ownerGlobal.ThirdPartyCookies;
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_background_tabs.js b/browser/base/content/test/trackingUI/browser_trackingUI_background_tabs.js
index a7edac71cb5f..d6fc1f1a2651 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_background_tabs.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_background_tabs.js
@@ -46,10 +46,7 @@ add_task(async function testBackgroundTabs() {
"Foreground tab has the correct content blocking event."
);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
await BrowserTestUtils.switchTab(gBrowser, backgroundTab);
@@ -65,7 +62,7 @@ add_task(async function testBackgroundTabs() {
"Foreground tab still has the correct content blocking event."
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
gBrowser.removeTab(backgroundTab);
gBrowser.removeTab(tab);
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_cookies_subview.js b/browser/base/content/test/trackingUI/browser_trackingUI_cookies_subview.js
index dd06f7ab6643..87900aecc82f 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_cookies_subview.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_cookies_subview.js
@@ -13,9 +13,13 @@ const CONTAINER_PAGE =
const TPC_PREF = "network.cookie.cookieBehavior";
add_task(async function setup() {
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
await UrlClassifierTestUtils.addTestTrackers();
registerCleanupFunction(() => {
+ Services.telemetry.canRecordExtended = oldCanRecord;
UrlClassifierTestUtils.cleanupTestTrackers();
});
});
@@ -44,7 +48,9 @@ async function assertSitesListed(
let [tab] = await Promise.all([promise, waitForContentBlockingEvent(count)]);
let browser = tab.linkedBrowser;
- await openProtectionsPopup();
+ await openIdentityPopup();
+
+ Services.telemetry.clearEvents();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cookies"
@@ -57,6 +63,17 @@ async function assertSitesListed(
ok(true, "Cookies view was shown");
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent;
+ let buttonEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "cookies_subview_btn"
+ );
+ is(buttonEvents.length, 1, "recorded telemetry for the button click");
+
let listHeaders = cookiesView.querySelectorAll(
".identity-popup-cookiesView-list-header"
);
@@ -112,7 +129,7 @@ async function assertSitesListed(
);
}
- let mainView = document.getElementById("protections-popup-mainView");
+ let mainView = document.getElementById("identity-popup-mainView");
viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
let backButton = cookiesView.querySelector(".subviewbutton-back");
backButton.click();
@@ -284,7 +301,7 @@ add_task(async function testCookiesSubViewAllowed() {
});
let [tab] = await Promise.all([promise, waitForContentBlockingEvent(3)]);
- await openProtectionsPopup();
+ await openIdentityPopup();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cookies"
@@ -400,7 +417,7 @@ add_task(async function testCookiesSubViewAllowedHeuristic() {
await new Promise(resolve => waitForFocus(resolve, popup));
await new Promise(resolve => waitForFocus(resolve, window));
- await openProtectionsPopup();
+ await openIdentityPopup();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cookies"
@@ -483,7 +500,7 @@ add_task(async function testCookiesSubViewBlockedDoublyNested() {
});
let [tab] = await Promise.all([promise, waitForContentBlockingEvent(3)]);
- await openProtectionsPopup();
+ await openIdentityPopup();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cookies"
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_cryptominers.js b/browser/base/content/test/trackingUI/browser_trackingUI_cryptominers.js
index c76f1f4e288b..c24b6548809a 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_cryptominers.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_cryptominers.js
@@ -1,3 +1,4 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
@@ -49,22 +50,22 @@ async function testIdentityState(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.disableForCurrentPage();
+ ContentBlocking.disableForCurrentPage();
await loaded;
}
ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
+ !ContentBlocking.content.hasAttribute("detected"),
"cryptominers are not detected"
);
if (hasException) {
ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ !BrowserTestUtils.is_hidden(ContentBlocking.iconBox),
"icon box is visible to indicate the exception"
);
} else {
ok(
- BrowserTestUtils.is_hidden(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_hidden(ContentBlocking.iconBox),
"icon box is not visible"
);
}
@@ -77,16 +78,13 @@ async function testIdentityState(hasException) {
await promise;
+ ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_visible(ContentBlocking.iconBox),
"icon box is visible"
);
is(
- gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ ContentBlocking.iconBox.hasAttribute("hasException"),
hasException,
"Shows an exception when appropriate"
);
@@ -97,7 +95,7 @@ async function testIdentityState(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.enableForCurrentPage();
+ ContentBlocking.enableForCurrentPage();
await loaded;
}
@@ -121,7 +119,7 @@ async function testSubview(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.disableForCurrentPage();
+ ContentBlocking.disableForCurrentPage();
await loaded;
}
@@ -131,7 +129,7 @@ async function testSubview(hasException) {
});
await promise;
- await openProtectionsPopup();
+ await openIdentityPopup();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cryptominers"
@@ -159,7 +157,7 @@ async function testSubview(hasException) {
"Indicates the miner was blocked or allowed"
);
- let mainView = document.getElementById("protections-popup-mainView");
+ let mainView = document.getElementById("identity-popup-mainView");
viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
let backButton = subview.querySelector(".subviewbutton-back");
backButton.click();
@@ -173,7 +171,7 @@ async function testSubview(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.enableForCurrentPage();
+ ContentBlocking.enableForCurrentPage();
await loaded;
}
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_fetch.js b/browser/base/content/test/trackingUI/browser_trackingUI_fetch.js
index c5166098c80f..2c94546e5ead 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_fetch.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_fetch.js
@@ -18,19 +18,16 @@ add_task(async function test_fetch() {
});
await contentBlockingEvent;
- let gProtectionsHandler = newTabBrowser.ownerGlobal.gProtectionsHandler;
- ok(gProtectionsHandler, "got CB object");
+ let ContentBlocking = newTabBrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "got CB object");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
+ ContentBlocking.content.hasAttribute("detected"),
"has detected content blocking"
);
- ok(
- gProtectionsHandler.iconBox.hasAttribute("active"),
- "icon box is active"
- );
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "icon box is active");
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"),
"correct tooltip"
);
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_fingerprinters.js b/browser/base/content/test/trackingUI/browser_trackingUI_fingerprinters.js
index 02ea9ca60bb1..79d403509beb 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_fingerprinters.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_fingerprinters.js
@@ -1,3 +1,4 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
@@ -49,22 +50,22 @@ async function testIdentityState(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.disableForCurrentPage();
+ ContentBlocking.disableForCurrentPage();
await loaded;
}
ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
+ !ContentBlocking.content.hasAttribute("detected"),
"fingerprinters are not detected"
);
if (hasException) {
ok(
- !BrowserTestUtils.is_hidden(gProtectionsHandler.iconBox),
+ !BrowserTestUtils.is_hidden(ContentBlocking.iconBox),
"icon box is visible to indicate the exception"
);
} else {
ok(
- BrowserTestUtils.is_hidden(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_hidden(ContentBlocking.iconBox),
"icon box is not visible"
);
}
@@ -77,16 +78,13 @@ async function testIdentityState(hasException) {
await promise;
+ ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_visible(ContentBlocking.iconBox),
"icon box is visible"
);
is(
- gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ ContentBlocking.iconBox.hasAttribute("hasException"),
hasException,
"Shows an exception when appropriate"
);
@@ -97,7 +95,7 @@ async function testIdentityState(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.enableForCurrentPage();
+ ContentBlocking.enableForCurrentPage();
await loaded;
}
@@ -121,7 +119,7 @@ async function testSubview(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.disableForCurrentPage();
+ ContentBlocking.disableForCurrentPage();
await loaded;
}
@@ -131,7 +129,7 @@ async function testSubview(hasException) {
});
await promise;
- await openProtectionsPopup();
+ await openIdentityPopup();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-fingerprinters"
@@ -159,7 +157,7 @@ async function testSubview(hasException) {
"Indicates the fingerprinter was blocked or allowed"
);
- let mainView = document.getElementById("protections-popup-mainView");
+ let mainView = document.getElementById("identity-popup-mainView");
viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
let backButton = subview.querySelector(".subviewbutton-back");
backButton.click();
@@ -173,7 +171,7 @@ async function testSubview(hasException) {
false,
TRACKING_PAGE
);
- gProtectionsHandler.enableForCurrentPage();
+ ContentBlocking.enableForCurrentPage();
await loaded;
}
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js b/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
index 2ec98ecc3c1b..a7ffedb8c54d 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_open_preferences.js
@@ -8,11 +8,9 @@ const TPC_PREF = "network.cookie.cookieBehavior";
const TRACKING_PAGE =
"http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
-async function waitAndAssertPreferencesShown(_spotlight, identityPopup) {
+async function waitAndAssertPreferencesShown(_spotlight) {
await BrowserTestUtils.waitForEvent(
- identityPopup
- ? gIdentityHandler._identityPopup
- : gProtectionsHandler._protectionsPopup,
+ gIdentityHandler._identityPopup,
"popuphidden"
);
await TestUtils.waitForCondition(
@@ -51,11 +49,16 @@ add_task(async function setup() {
});
});
-// Tests that pressing the content blocking preferences icon in the protections popup
+// Tests that pressing the content blocking preferences icon in the identity popup
// links to about:preferences
add_task(async function testOpenPreferencesFromCBPrefsButton() {
await BrowserTestUtils.withNewTab("https://example.com", async function() {
- await openProtectionsPopup();
+ let promisePanelOpen = BrowserTestUtils.waitForEvent(
+ gIdentityHandler._identityPopup,
+ "popupshown"
+ );
+ gIdentityHandler._identityBox.click();
+ await promisePanelOpen;
let preferencesButton = document.getElementById(
"tracking-protection-preferences-button"
@@ -66,9 +69,23 @@ add_task(async function testOpenPreferencesFromCBPrefsButton() {
"The preferences button is shown."
);
+ Services.telemetry.clearEvents();
+
let shown = waitAndAssertPreferencesShown("trackingprotection");
preferencesButton.click();
await shown;
+
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ let clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "cb_prefs_button"
+ );
+ is(clickEvents.length, 1, "recorded telemetry for the click");
});
});
@@ -76,7 +93,12 @@ add_task(async function testOpenPreferencesFromCBPrefsButton() {
// links to about:preferences
add_task(async function testOpenPreferencesFromPermissionsPrefsButton() {
await BrowserTestUtils.withNewTab("https://example.com", async function() {
- await openIdentityPopup();
+ let promisePanelOpen = BrowserTestUtils.waitForEvent(
+ gIdentityHandler._identityPopup,
+ "popupshown"
+ );
+ gIdentityHandler._identityBox.click();
+ await promisePanelOpen;
let preferencesButton = document.getElementById(
"identity-popup-permission-preferences-button"
@@ -89,7 +111,7 @@ add_task(async function testOpenPreferencesFromPermissionsPrefsButton() {
Services.telemetry.clearEvents();
- let shown = waitAndAssertPreferencesShown("permissions", true);
+ let shown = waitAndAssertPreferencesShown("permissions");
preferencesButton.click();
await shown;
@@ -113,7 +135,12 @@ add_task(async function testOpenPreferencesFromTrackersSubview() {
Services.prefs.setBoolPref(TP_PREF, true);
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
- await openProtectionsPopup();
+ let promisePanelOpen = BrowserTestUtils.waitForEvent(
+ gIdentityHandler._identityPopup,
+ "popupshown"
+ );
+ gIdentityHandler._identityBox.click();
+ await promisePanelOpen;
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-tracking-protection"
@@ -138,9 +165,23 @@ add_task(async function testOpenPreferencesFromTrackersSubview() {
"The preferences button is shown."
);
+ Services.telemetry.clearEvents();
+
let shown = waitAndAssertPreferencesShown("trackingprotection");
preferencesButton.click();
await shown;
+
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ let clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "trackers_prefs_btn"
+ );
+ is(clickEvents.length, 1, "recorded telemetry for the click");
});
Services.prefs.clearUserPref(TP_PREF);
@@ -155,7 +196,12 @@ add_task(async function testOpenPreferencesFromCookiesSubview() {
);
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
- await openProtectionsPopup();
+ let promisePanelOpen = BrowserTestUtils.waitForEvent(
+ gIdentityHandler._identityPopup,
+ "popupshown"
+ );
+ gIdentityHandler._identityBox.click();
+ await promisePanelOpen;
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-cookies"
@@ -180,9 +226,23 @@ add_task(async function testOpenPreferencesFromCookiesSubview() {
"The preferences button is shown."
);
+ Services.telemetry.clearEvents();
+
let shown = waitAndAssertPreferencesShown("trackingprotection");
preferencesButton.click();
await shown;
+
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ let clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "cookies_prefs_btn"
+ );
+ is(clickEvents.length, 1, "recorded telemetry for the click");
});
Services.prefs.clearUserPref(TPC_PREF);
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js b/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
index 5a7a33b95170..fc7cb2f068af 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_pbmode_exceptions.js
@@ -9,13 +9,13 @@ const TRACKING_PAGE =
"http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
const DTSCBN_PREF = "dom.testing.sync-content-blocking-notifications";
var TrackingProtection = null;
-var gProtectionsHandler = null;
+var ContentBlocking = null;
var browser = null;
registerCleanupFunction(function() {
Services.prefs.clearUserPref(TP_PB_PREF);
Services.prefs.clearUserPref(DTSCBN_PREF);
- gProtectionsHandler = TrackingProtection = browser = null;
+ ContentBlocking = TrackingProtection = browser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
});
@@ -26,9 +26,9 @@ function hidden(sel) {
return display === "none";
}
-function protectionsPopupState() {
+function identityPopupState() {
let win = browser.ownerGlobal;
- return win.document.getElementById("protections-popup").state;
+ return win.document.getElementById("identity-popup").state;
}
function clickButton(sel) {
@@ -39,30 +39,43 @@ function clickButton(sel) {
function testTrackingPage(window) {
info("Tracking content must be blocked");
+ ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ !ContentBlocking.content.hasAttribute("hasException"),
"content shows no exception"
);
ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_visible(ContentBlocking.iconBox),
"icon box is visible"
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
ok(
- !gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ !ContentBlocking.iconBox.hasAttribute("hasException"),
"icon box shows no exception"
);
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"),
"correct tooltip"
);
+ ok(hidden("#tracking-action-block"), "blockButton is hidden");
+
+ if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+ ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
+ ok(
+ !hidden("#tracking-action-unblock-private"),
+ "unblockButtonPrivate is visible"
+ );
+ } 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"
@@ -75,30 +88,29 @@ function testTrackingPage(window) {
function testTrackingPageUnblocked() {
info("Tracking content must be white-listed and not blocked");
+ ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ ContentBlocking.content.hasAttribute("hasException"),
"content shows exception"
);
- ok(!gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
ok(
- gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ ContentBlocking.iconBox.hasAttribute("hasException"),
"shield shows exception"
);
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"),
"correct tooltip"
);
ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ 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-not-detected"),
@@ -123,8 +135,8 @@ add_task(async function testExceptionAddition() {
waitForStateStop: true,
});
- gProtectionsHandler = browser.ownerGlobal.gProtectionsHandler;
- ok(gProtectionsHandler, "CB is attached to the private window");
+ ContentBlocking = browser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
@@ -141,8 +153,8 @@ add_task(async function testExceptionAddition() {
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
- gProtectionsHandler.disableForCurrentPage();
- is(protectionsPopupState(), "closed", "protections popup is closed");
+ clickButton("#tracking-action-unblock");
+ is(identityPopupState(), "closed", "Identity popup is closed");
await tabReloadPromise;
testTrackingPageUnblocked();
@@ -171,8 +183,8 @@ add_task(async function testExceptionPersistence() {
waitForStateStop: true,
});
- gProtectionsHandler = browser.ownerGlobal.gProtectionsHandler;
- ok(gProtectionsHandler, "CB is attached to the private window");
+ ContentBlocking = browser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
@@ -188,8 +200,8 @@ add_task(async function testExceptionPersistence() {
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
- gProtectionsHandler.disableForCurrentPage();
- is(protectionsPopupState(), "closed", "protections popup is closed");
+ clickButton("#tracking-action-unblock");
+ is(identityPopupState(), "closed", "Identity popup is closed");
await Promise.all([
tabReloadPromise,
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
index d011e367781c..e9840173b213 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -28,7 +28,12 @@ let { Preferences } = ChromeUtils.import(
add_task(async function setup() {
await UrlClassifierTestUtils.addTestTrackers();
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
registerCleanupFunction(() => {
+ Services.telemetry.canRecordExtended = oldCanRecord;
+
// Clear prefs that are touched in this test again for sanity.
Services.prefs.clearUserPref(TP_PREF);
Services.prefs.clearUserPref(CB_PREF);
@@ -127,10 +132,10 @@ add_task(async function testReportBreakageVisibility() {
}
await BrowserTestUtils.withNewTab(scenario.url, async function() {
- await openProtectionsPopup();
+ await openIdentityPopup();
let reportBreakageButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
+ "identity-popup-content-blocking-report-breakage"
);
await TestUtils.waitForCondition(
() =>
@@ -153,40 +158,44 @@ add_task(async function testReportBreakageCancel() {
Services.prefs.setBoolPref(PREF_REPORT_BREAKAGE_ENABLED, true);
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
- await openProtectionsPopup();
+ await openIdentityPopup();
- let siteNotWorkingButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
+ Services.telemetry.clearEvents();
+
+ let reportBreakageButton = document.getElementById(
+ "identity-popup-content-blocking-report-breakage"
);
ok(
- BrowserTestUtils.is_visible(siteNotWorkingButton),
- "site not working button is visible"
+ BrowserTestUtils.is_visible(reportBreakageButton),
+ "report breakage button is visible"
);
- let siteNotWorkingView = document.getElementById(
- "protections-popup-siteNotWorkingView"
+ let reportBreakageView = document.getElementById(
+ "identity-popup-breakageReportView"
);
let viewShown = BrowserTestUtils.waitForEvent(
- siteNotWorkingView,
+ reportBreakageView,
"ViewShown"
);
- siteNotWorkingButton.click();
+ reportBreakageButton.click();
await viewShown;
- let sendReportButton = document.getElementById(
- "protections-popup-siteNotWorkingView-sendReport"
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent;
+ let clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "report_breakage"
);
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- sendReportButton.click();
- await viewShown;
+ is(clickEvents.length, 1, "recorded telemetry for the click");
ok(true, "Report breakage view was shown");
- viewShown = BrowserTestUtils.waitForEvent(siteNotWorkingView, "ViewShown");
+ let mainView = document.getElementById("identity-popup-mainView");
+ viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
let cancelButton = document.getElementById(
- "protections-popup-sendReportView-cancel"
+ "identity-popup-breakageReportView-cancel"
);
cancelButton.click();
await viewShown;
@@ -268,54 +277,42 @@ async function testReportBreakage(url, tags) {
Services.prefs.setBoolPref(PREF_REPORT_BREAKAGE_ENABLED, true);
Services.prefs.setStringPref(PREF_REPORT_BREAKAGE_URL, path);
- await openProtectionsPopup();
-
- let siteNotWorkingButton = document.getElementById(
- "protections-popup-tp-switch-breakage-link"
- );
- await TestUtils.waitForCondition(
- () => BrowserTestUtils.is_visible(siteNotWorkingButton),
- "site not working button is visible"
- );
- let siteNotWorkingView = document.getElementById(
- "protections-popup-siteNotWorkingView"
- );
- let viewShown = BrowserTestUtils.waitForEvent(
- siteNotWorkingView,
- "ViewShown"
- );
- siteNotWorkingButton.click();
- await viewShown;
-
- let sendReportButton = document.getElementById(
- "protections-popup-siteNotWorkingView-sendReport"
- );
- let sendReportView = document.getElementById(
- "protections-popup-sendReportView"
- );
- viewShown = BrowserTestUtils.waitForEvent(sendReportView, "ViewShown");
- sendReportButton.click();
- await viewShown;
-
- ok(true, "Report breakage view was shown");
+ await openIdentityPopup();
let comments = document.getElementById(
- "protections-popup-sendReportView-collection-comments"
+ "identity-popup-breakageReportView-collection-comments"
);
is(comments.value, "", "Comments textarea should initially be empty");
+ let reportBreakageButton = document.getElementById(
+ "identity-popup-content-blocking-report-breakage"
+ );
+ await TestUtils.waitForCondition(
+ () => BrowserTestUtils.is_visible(reportBreakageButton),
+ "report breakage button is visible"
+ );
+ let reportBreakageView = document.getElementById(
+ "identity-popup-breakageReportView"
+ );
+ let viewShown = BrowserTestUtils.waitForEvent(
+ reportBreakageView,
+ "ViewShown"
+ );
+ reportBreakageButton.click();
+ await viewShown;
+
let submitButton = document.getElementById(
- "protections-popup-sendReportView-submit"
+ "identity-popup-breakageReportView-submit"
);
let reportURL = document.getElementById(
- "protections-popup-sendReportView-collection-url"
+ "identity-popup-breakageReportView-collection-url"
).value;
is(reportURL, url, "Shows the correct URL in the report UI.");
// Make sure that sending the report closes the identity popup.
let popuphidden = BrowserTestUtils.waitForEvent(
- gProtectionsHandler._protectionsPopup,
+ gIdentityHandler._identityPopup,
"popuphidden"
);
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_state.js b/browser/base/content/test/trackingUI/browser_trackingUI_state.js
index 57165dec2363..9aa2083b5450 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_state.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_state.js
@@ -24,14 +24,14 @@ const TRACKING_PAGE =
"http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
const COOKIE_PAGE =
"http://not-tracking.example.com/browser/browser/base/content/test/trackingUI/cookiePage.html";
-var gProtectionsHandler = null;
+var ContentBlocking = null;
var TrackingProtection = null;
var ThirdPartyCookies = null;
var tabbrowser = null;
var gTrackingPageURL = TRACKING_PAGE;
registerCleanupFunction(function() {
- TrackingProtection = gProtectionsHandler = ThirdPartyCookies = tabbrowser = null;
+ TrackingProtection = ContentBlocking = ThirdPartyCookies = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(TP_PREF);
Services.prefs.clearUserPref(TP_PB_PREF);
@@ -59,31 +59,27 @@ function clickButton(sel) {
function testBenignPage() {
info("Non-tracking content must not be blocked");
ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
+ !ContentBlocking.content.hasAttribute("detected"),
"no trackers are detected"
);
ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ !ContentBlocking.content.hasAttribute("hasException"),
"content shows no exception"
);
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ !ContentBlocking.iconBox.hasAttribute("hasException"),
"icon box shows no exception"
);
ok(
- !gProtectionsHandler.iconBox.hasAttribute("tooltiptext"),
+ !ContentBlocking.iconBox.hasAttribute("tooltiptext"),
"icon box has no tooltip"
);
- ok(
- BrowserTestUtils.is_hidden(gProtectionsHandler.iconBox),
- "icon box is hidden"
- );
+ 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-not-detected"),
@@ -106,32 +102,31 @@ function testBenignPage() {
function testBenignPageWithException() {
info("Non-tracking content must not be blocked");
ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
+ !ContentBlocking.content.hasAttribute("detected"),
"no trackers are detected"
);
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ ContentBlocking.content.hasAttribute("hasException"),
"content shows exception"
);
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
- ok(
- gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ ContentBlocking.iconBox.hasAttribute("hasException"),
"shield shows exception"
);
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"),
"correct tooltip"
);
ok(
- !BrowserTestUtils.is_hidden(gProtectionsHandler.iconBox),
+ !BrowserTestUtils.is_hidden(ContentBlocking.iconBox),
"icon box is not hidden"
);
+ ok(!hidden("#tracking-action-block"), "blockButton is visible");
+ ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(
!hidden("#identity-popup-content-blocking-not-detected"),
@@ -163,39 +158,57 @@ function areTrackersBlocked(isPrivateBrowsing) {
function testTrackingPage(window) {
info("Tracking content must be blocked");
+ ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- !gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ !ContentBlocking.content.hasAttribute("hasException"),
"content shows no exception"
);
let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
let blockedByTP = areTrackersBlocked(isWindowPrivate);
is(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ BrowserTestUtils.is_visible(ContentBlocking.iconBox),
blockedByTP,
"icon box is" + (blockedByTP ? "" : " not") + " visible"
);
is(
- gProtectionsHandler.iconBox.hasAttribute("active"),
+ ContentBlocking.iconBox.hasAttribute("active"),
blockedByTP,
"shield is" + (blockedByTP ? "" : " not") + " active"
);
ok(
- !gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ !ContentBlocking.iconBox.hasAttribute("hasException"),
"icon box shows no exception"
);
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
blockedByTP
? gNavigatorBundle.getString("trackingProtection.icon.activeTooltip")
: "",
"correct tooltip"
);
+ ok(hidden("#tracking-action-block"), "blockButton is hidden");
+
+ 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"
@@ -224,33 +237,29 @@ 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(
- gProtectionsHandler._protectionsPopup.hasAttribute("detected"),
- "trackers are detected"
- );
- ok(
- gProtectionsHandler._protectionsPopup.hasAttribute("hasException"),
+ ContentBlocking.content.hasAttribute("hasException"),
"content shows exception"
);
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
- ok(
- gProtectionsHandler.iconBox.hasAttribute("hasException"),
+ ContentBlocking.iconBox.hasAttribute("hasException"),
"shield shows exception"
);
is(
- gProtectionsHandler.iconBox.getAttribute("tooltiptext"),
+ ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"),
"correct tooltip"
);
ok(
- BrowserTestUtils.is_visible(gProtectionsHandler.iconBox),
+ 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-not-detected"),
@@ -306,7 +315,7 @@ async function testContentBlocking(tab) {
info("Disable CB for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
- tab.ownerGlobal.gProtectionsHandler.disableForCurrentPage();
+ clickButton("#tracking-action-unblock");
await tabReloadPromise;
let isPrivateBrowsing = PrivateBrowsingUtils.isWindowPrivate(tab.ownerGlobal);
let blockedByTP = areTrackersBlocked(isPrivateBrowsing);
@@ -314,7 +323,7 @@ async function testContentBlocking(tab) {
info("Re-enable TP for the page (which reloads the page)");
tabReloadPromise = promiseTabLoadEvent(tab);
- tab.ownerGlobal.gProtectionsHandler.enableForCurrentPage();
+ clickButton("#tracking-action-block");
await tabReloadPromise;
testTrackingPage(tab.ownerGlobal);
}
@@ -327,11 +336,8 @@ add_task(async function testNormalBrowsing() {
tabbrowser = gBrowser;
let tab = (tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser));
- gProtectionsHandler = gBrowser.ownerGlobal.gProtectionsHandler;
- ok(
- gProtectionsHandler,
- "gProtectionsHandler is attached to the browser window"
- );
+ ContentBlocking = gBrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the browser window");
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
is(
@@ -366,11 +372,8 @@ add_task(async function testPrivateBrowsing() {
Services.prefs.setIntPref(TPC_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
- gProtectionsHandler = tabbrowser.ownerGlobal.gProtectionsHandler;
- ok(
- gProtectionsHandler,
- "gProtectionsHandler is attached to the private window"
- );
+ ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
is(
@@ -398,11 +401,8 @@ add_task(async function testThirdPartyCookies() {
tabbrowser = gBrowser;
let tab = (tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser));
- gProtectionsHandler = gBrowser.ownerGlobal.gProtectionsHandler;
- ok(
- gProtectionsHandler,
- "gProtectionsHandler is attached to the browser window"
- );
+ ContentBlocking = gBrowser.ownerGlobal.ContentBlocking;
+ ok(ContentBlocking, "CB is attached to the browser window");
ThirdPartyCookies = gBrowser.ownerGlobal.ThirdPartyCookies;
ok(ThirdPartyCookies, "TP is attached to the browser window");
is(
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_state_reset.js b/browser/base/content/test/trackingUI/browser_trackingUI_state_reset.js
index 93222c44453f..99fbbd90eebf 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_state_reset.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_state_reset.js
@@ -23,10 +23,7 @@ add_task(async function testResetOnLocationChange() {
0,
"Benign page has no content blocking event"
);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
await Promise.all([
promiseTabLoadEvent(tab, TRACKING_PAGE),
@@ -38,7 +35,7 @@ add_task(async function testResetOnLocationChange() {
Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT,
"Tracking page has a content blocking event"
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
await promiseTabLoadEvent(tab, BENIGN_PAGE);
@@ -47,10 +44,7 @@ add_task(async function testResetOnLocationChange() {
0,
"Benign page has no content blocking event"
);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
let contentBlockingEvent = waitForContentBlockingEvent(3);
let trackingTab = await BrowserTestUtils.openNewForegroundTab(
@@ -64,7 +58,7 @@ add_task(async function testResetOnLocationChange() {
Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT,
"Tracking page has a content blocking event"
);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
gBrowser.selectedTab = tab;
is(
@@ -72,10 +66,7 @@ add_task(async function testResetOnLocationChange() {
0,
"Benign page has no content blocking event"
);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
gBrowser.removeTab(trackingTab);
gBrowser.removeTab(tab);
@@ -89,22 +80,16 @@ add_task(async function testResetOnTabChange() {
Services.prefs.setBoolPref(TP_PREF, true);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, ABOUT_PAGE);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
await Promise.all([
promiseTabLoadEvent(tab, TRACKING_PAGE),
waitForContentBlockingEvent(3),
]);
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
await promiseTabLoadEvent(tab, ABOUT_PAGE);
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
let contentBlockingEvent = waitForContentBlockingEvent(3);
let trackingTab = await BrowserTestUtils.openNewForegroundTab(
@@ -112,13 +97,10 @@ add_task(async function testResetOnTabChange() {
TRACKING_PAGE
);
await contentBlockingEvent;
- ok(gProtectionsHandler.iconBox.hasAttribute("active"), "shield is active");
+ ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
gBrowser.selectedTab = tab;
- ok(
- !gProtectionsHandler.iconBox.hasAttribute("active"),
- "shield is not active"
- );
+ ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
gBrowser.removeTab(trackingTab);
gBrowser.removeTab(tab);
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js b/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
index 2007aed892a2..f2d3a520eacf 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
@@ -59,7 +59,7 @@ add_task(async function testShieldHistogram() {
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
- gProtectionsHandler.disableForCurrentPage();
+ document.querySelector("#tracking-action-unblock").doCommand();
await tabReloadPromise;
is(getShieldCounts()[0], 3, "Adds one more page load");
is(
@@ -70,7 +70,7 @@ add_task(async function testShieldHistogram() {
info("Re-enable TP for the page (which reloads the page)");
tabReloadPromise = promiseTabLoadEvent(tab);
- gProtectionsHandler.enableForCurrentPage();
+ document.querySelector("#tracking-action-block").doCommand();
await tabReloadPromise;
is(getShieldCounts()[0], 4, "Adds one more page load");
is(
@@ -84,3 +84,78 @@ add_task(async function testShieldHistogram() {
// Reset these to make counting easier for the next test
getShieldHistogram().clear();
});
+
+add_task(async function testIdentityPopupEvents() {
+ Services.prefs.setBoolPref(PREF, true);
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+
+ await promiseTabLoadEvent(tab, BENIGN_PAGE);
+
+ Services.telemetry.clearEvents();
+
+ await openIdentityPopup();
+
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ let openEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "open" &&
+ e[3] == "identity_popup"
+ );
+ is(openEvents.length, 1, "recorded telemetry for opening the identity popup");
+ is(openEvents[0][4], "shield-hidden", "recorded the shield as hidden");
+
+ await promiseTabLoadEvent(tab, TRACKING_PAGE);
+
+ await openIdentityPopup();
+
+ events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ openEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "open" &&
+ e[3] == "identity_popup"
+ );
+ is(openEvents.length, 1, "recorded telemetry for opening the identity popup");
+ is(openEvents[0][4], "shield-showing", "recorded the shield as showing");
+
+ info("Disable TP for the page (which reloads the page)");
+ let tabReloadPromise = promiseTabLoadEvent(tab);
+ document.querySelector("#tracking-action-unblock").doCommand();
+ await tabReloadPromise;
+
+ events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ let clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "unblock"
+ );
+ is(clickEvents.length, 1, "recorded telemetry for the click");
+
+ info("Re-enable TP for the page (which reloads the page)");
+ tabReloadPromise = promiseTabLoadEvent(tab);
+ document.querySelector("#tracking-action-block").doCommand();
+ await tabReloadPromise;
+
+ events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
+ true
+ ).parent;
+ clickEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "block"
+ );
+ is(clickEvents.length, 1, "recorded telemetry for the click");
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js b/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
index 3fbd49fbac95..f8c03241082a 100644
--- a/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
@@ -10,16 +10,22 @@ const TRACKING_PAGE =
const TP_PREF = "privacy.trackingprotection.enabled";
add_task(async function setup() {
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
await UrlClassifierTestUtils.addTestTrackers();
registerCleanupFunction(() => {
+ Services.telemetry.canRecordExtended = oldCanRecord;
UrlClassifierTestUtils.cleanupTestTrackers();
});
});
async function assertSitesListed(blocked) {
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function(browser) {
- await openProtectionsPopup();
+ await openIdentityPopup();
+
+ Services.telemetry.clearEvents();
let categoryItem = document.getElementById(
"identity-popup-content-blocking-category-tracking-protection"
@@ -35,6 +41,17 @@ async function assertSitesListed(blocked) {
ok(true, "Trackers view was shown");
+ let events = Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent;
+ let buttonEvents = events.filter(
+ e =>
+ e[1] == "security.ui.identitypopup" &&
+ e[2] == "click" &&
+ e[3] == "trackers_subview_btn"
+ );
+ is(buttonEvents.length, 1, "recorded telemetry for the button click");
+
let listItems = trackersView.querySelectorAll(
".identity-popup-content-blocking-list-item"
);
@@ -49,7 +66,7 @@ async function assertSitesListed(blocked) {
"Strict info is hidden if TP is enabled."
);
- let mainView = document.getElementById("protections-popup-mainView");
+ let mainView = document.getElementById("identity-popup-mainView");
viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
let backButton = trackersView.querySelector(".subviewbutton-back");
backButton.click();
diff --git a/browser/base/content/test/trackingUI/head.js b/browser/base/content/test/trackingUI/head.js
index a0b6adc71862..1aead5f03e52 100644
--- a/browser/base/content/test/trackingUI/head.js
+++ b/browser/base/content/test/trackingUI/head.js
@@ -2,12 +2,6 @@ var { UrlClassifierTestUtils } = ChromeUtils.import(
"resource://testing-common/UrlClassifierTestUtils.jsm"
);
-ChromeUtils.defineModuleGetter(
- this,
- "ContentBlockingAllowList",
- "resource://gre/modules/ContentBlockingAllowList.jsm"
-);
-
/**
* Waits for a load (or custom) event to finish in a given tab. If provided
* load an uri into the tab.
@@ -49,14 +43,6 @@ function openIdentityPopup() {
return viewShown;
}
-function openProtectionsPopup() {
- let mainView = document.getElementById("protections-popup-mainView");
- let viewShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
- // TODO: This should click on the icon once we have it.
- gProtectionsHandler.showProtectionsPopup();
- return viewShown;
-}
-
function waitForSecurityChange(numChanges = 1, win = null) {
if (!win) {
win = window;
diff --git a/browser/base/jar.mn b/browser/base/jar.mn
index 11057de4897d..9bb026fe117a 100644
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -37,6 +37,7 @@ browser.jar:
content/browser/browser-ctrlTab.js (content/browser-ctrlTab.js)
content/browser/browser-customization.js (content/browser-customization.js)
content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
+ content/browser/browser-contentblocking.js (content/browser-contentblocking.js)
#ifndef MOZILLA_OFFICIAL
content/browser/browser-development-helpers.js (content/browser-development-helpers.js)
#endif
diff --git a/browser/components/controlcenter/content/identityPanel.inc.xul b/browser/components/controlcenter/content/identityPanel.inc.xul
index 88dfc0c85554..21e07888a260 100644
--- a/browser/components/controlcenter/content/identityPanel.inc.xul
+++ b/browser/components/controlcenter/content/identityPanel.inc.xul
@@ -56,6 +56,80 @@
oncommand="gIdentityHandler.showSecuritySubView(); gIdentityHandler.recordClick('security_subview_btn');"/>
+
+
+
-
-
-
-