зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1557872
- Add a new JS module for manipulating the Content Blocking allow list; r=nhnt11
Differential Revision: https://phabricator.services.mozilla.com/D34355 --HG-- extra : source : 832579daee7c9e328d220611ab8929a1a4cf150b
This commit is contained in:
Родитель
ea1728721a
Коммит
caea64f895
|
@ -2,6 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
ChromeUtils.defineModuleGetter(this, "ContentBlockingAllowList",
|
||||||
|
"resource://gre/modules/ContentBlockingAllowList.jsm");
|
||||||
|
|
||||||
var Fingerprinting = {
|
var Fingerprinting = {
|
||||||
PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
|
PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
|
||||||
reportBreakageLabel: "fingerprinting",
|
reportBreakageLabel: "fingerprinting",
|
||||||
|
@ -1087,19 +1090,15 @@ var ContentBlocking = {
|
||||||
onLocationChange() {
|
onLocationChange() {
|
||||||
// Reset blocking and exception status so that we can send telemetry
|
// Reset blocking and exception status so that we can send telemetry
|
||||||
this.hadShieldState = false;
|
this.hadShieldState = false;
|
||||||
let baseURI = this._baseURIForChannelClassifier;
|
|
||||||
|
|
||||||
// Don't deal with about:, file: etc.
|
// Don't deal with about:, file: etc.
|
||||||
if (!baseURI) {
|
if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBrowserPrivate = PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
// Check whether the user has added an exception for this site.
|
// Check whether the user has added an exception for this site.
|
||||||
let type = isBrowserPrivate ? "trackingprotection-pb" : "trackingprotection";
|
let hasException =
|
||||||
let hasException = Services.perms.testExactPermission(baseURI, type) ==
|
ContentBlockingAllowList.includes(gBrowser.selectedBrowser);
|
||||||
Services.perms.ALLOW_ACTION;
|
|
||||||
|
|
||||||
this.content.toggleAttribute("hasException", hasException);
|
this.content.toggleAttribute("hasException", hasException);
|
||||||
this.protectionsPopup.toggleAttribute("hasException", hasException);
|
this.protectionsPopup.toggleAttribute("hasException", hasException);
|
||||||
|
@ -1113,10 +1112,9 @@ var ContentBlocking = {
|
||||||
|
|
||||||
onContentBlockingEvent(event, webProgress, isSimulated) {
|
onContentBlockingEvent(event, webProgress, isSimulated) {
|
||||||
let previousState = gBrowser.securityUI.contentBlockingEvent;
|
let previousState = gBrowser.securityUI.contentBlockingEvent;
|
||||||
let baseURI = this._baseURIForChannelClassifier;
|
|
||||||
|
|
||||||
// Don't deal with about:, file: etc.
|
// Don't deal with about:, file: etc.
|
||||||
if (!baseURI) {
|
if (!ContentBlockingAllowList.canHandle(gBrowser.selectedBrowser)) {
|
||||||
this.iconBox.removeAttribute("animate");
|
this.iconBox.removeAttribute("animate");
|
||||||
this.iconBox.removeAttribute("active");
|
this.iconBox.removeAttribute("active");
|
||||||
this.iconBox.removeAttribute("hasException");
|
this.iconBox.removeAttribute("hasException");
|
||||||
|
@ -1139,12 +1137,9 @@ var ContentBlocking = {
|
||||||
anyBlocking = anyBlocking || blocker.activated;
|
anyBlocking = anyBlocking || blocker.activated;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBrowserPrivate = PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
// Check whether the user has added an exception for this site.
|
// Check whether the user has added an exception for this site.
|
||||||
let type = isBrowserPrivate ? "trackingprotection-pb" : "trackingprotection";
|
let hasException =
|
||||||
let hasException = Services.perms.testExactPermission(baseURI, type) ==
|
ContentBlockingAllowList.includes(gBrowser.selectedBrowser);
|
||||||
Services.perms.ALLOW_ACTION;
|
|
||||||
|
|
||||||
// Reset the animation in case the user is switching tabs or if no blockers were detected
|
// 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
|
// (this is most likely happening because the user navigated on to a different site). This
|
||||||
|
@ -1156,6 +1151,7 @@ var ContentBlocking = {
|
||||||
} else if (anyBlocking && !this.iconBox.hasAttribute("active")) {
|
} else if (anyBlocking && !this.iconBox.hasAttribute("active")) {
|
||||||
this.iconBox.setAttribute("animate", "true");
|
this.iconBox.setAttribute("animate", "true");
|
||||||
|
|
||||||
|
let isBrowserPrivate = PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser);
|
||||||
if (!isBrowserPrivate) {
|
if (!isBrowserPrivate) {
|
||||||
let introCount = Services.prefs.getIntPref(this.prefIntroCount);
|
let introCount = Services.prefs.getIntPref(this.prefIntroCount);
|
||||||
let installStamp = Services.prefs.getIntPref(
|
let installStamp = Services.prefs.getIntPref(
|
||||||
|
@ -1230,32 +1226,13 @@ var ContentBlocking = {
|
||||||
},
|
},
|
||||||
|
|
||||||
disableForCurrentPage() {
|
disableForCurrentPage() {
|
||||||
let baseURI = this._baseURIForChannelClassifier;
|
ContentBlockingAllowList.add(gBrowser.selectedBrowser);
|
||||||
|
|
||||||
// Add the current host in the 'trackingprotection' consumer of
|
|
||||||
// the permission manager using a normalized URI. This effectively
|
|
||||||
// places this host on the tracking protection allowlist.
|
|
||||||
if (PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser)) {
|
|
||||||
PrivateBrowsingUtils.addToTrackingAllowlist(baseURI);
|
|
||||||
} else {
|
|
||||||
Services.perms.add(baseURI,
|
|
||||||
"trackingprotection", Services.perms.ALLOW_ACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hideIdentityPopupAndReload();
|
this.hideIdentityPopupAndReload();
|
||||||
},
|
},
|
||||||
|
|
||||||
enableForCurrentPage() {
|
enableForCurrentPage() {
|
||||||
// Remove the current host from the 'trackingprotection' consumer
|
ContentBlockingAllowList.remove(gBrowser.selectedBrowser);
|
||||||
// of the permission manager. This effectively removes this host
|
|
||||||
// from the tracking protection allowlist.
|
|
||||||
let baseURI = this._baseURIForChannelClassifier;
|
|
||||||
|
|
||||||
if (PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser)) {
|
|
||||||
PrivateBrowsingUtils.removeFromTrackingAllowlist(baseURI);
|
|
||||||
} else {
|
|
||||||
Services.perms.remove(baseURI, "trackingprotection");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hideIdentityPopupAndReload();
|
this.hideIdentityPopupAndReload();
|
||||||
},
|
},
|
||||||
|
|
|
@ -181,22 +181,17 @@ async function testContentBlocking(tab) {
|
||||||
testBenignPage();
|
testBenignPage();
|
||||||
|
|
||||||
info("Load a test page not containing tracking elements which has an exception.");
|
info("Load a test page not containing tracking elements which has an exception.");
|
||||||
let isPrivateBrowsing = PrivateBrowsingUtils.isWindowPrivate(tab.ownerGlobal);
|
|
||||||
let uri = Services.io.newURI("https://example.org/");
|
|
||||||
if (isPrivateBrowsing) {
|
|
||||||
PrivateBrowsingUtils.addToTrackingAllowlist(uri);
|
|
||||||
} else {
|
|
||||||
Services.perms.add(uri, "trackingprotection", Services.perms.ALLOW_ACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
await promiseTabLoadEvent(tab, uri.spec);
|
await promiseTabLoadEvent(tab, "https://example.org/?round=1");
|
||||||
|
|
||||||
|
ContentBlockingAllowList.add(tab.linkedBrowser);
|
||||||
|
// Load another page from the same origin to ensure there is an onlocationchange
|
||||||
|
// notification which would trigger an oncontentblocking notification for us.
|
||||||
|
await promiseTabLoadEvent(tab, "https://example.org/?round=2");
|
||||||
|
|
||||||
testBenignPageWithException();
|
testBenignPageWithException();
|
||||||
|
|
||||||
if (isPrivateBrowsing) {
|
ContentBlockingAllowList.remove(tab.linkedBrowser);
|
||||||
PrivateBrowsingUtils.removeFromTrackingAllowlist(uri);
|
|
||||||
} else {
|
|
||||||
Services.perms.remove(uri, "trackingprotection");
|
|
||||||
}
|
|
||||||
|
|
||||||
info("Load a test page containing tracking elements");
|
info("Load a test page containing tracking elements");
|
||||||
await promiseTabLoadEvent(tab, gTrackingPageURL);
|
await promiseTabLoadEvent(tab, gTrackingPageURL);
|
||||||
|
@ -206,6 +201,7 @@ async function testContentBlocking(tab) {
|
||||||
let tabReloadPromise = promiseTabLoadEvent(tab);
|
let tabReloadPromise = promiseTabLoadEvent(tab);
|
||||||
clickButton("#tracking-action-unblock");
|
clickButton("#tracking-action-unblock");
|
||||||
await tabReloadPromise;
|
await tabReloadPromise;
|
||||||
|
let isPrivateBrowsing = PrivateBrowsingUtils.isWindowPrivate(tab.ownerGlobal);
|
||||||
let blockedByTP = areTrackersBlocked(isPrivateBrowsing);
|
let blockedByTP = areTrackersBlocked(isPrivateBrowsing);
|
||||||
testTrackingPageUnblocked(blockedByTP, tab.ownerGlobal);
|
testTrackingPageUnblocked(blockedByTP, tab.ownerGlobal);
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,9 @@ ChromeUtils.defineModuleGetter(this, "FormLikeFactory",
|
||||||
ChromeUtils.defineModuleGetter(this, "GeckoViewAutoFill",
|
ChromeUtils.defineModuleGetter(this, "GeckoViewAutoFill",
|
||||||
"resource://gre/modules/GeckoViewAutoFill.jsm");
|
"resource://gre/modules/GeckoViewAutoFill.jsm");
|
||||||
|
|
||||||
|
ChromeUtils.defineModuleGetter(this, "ContentBlockingAllowList",
|
||||||
|
"resource://gre/modules/ContentBlockingAllowList.jsm");
|
||||||
|
|
||||||
var GlobalEventDispatcher = EventDispatcher.instance;
|
var GlobalEventDispatcher = EventDispatcher.instance;
|
||||||
var WindowEventDispatcher = EventDispatcher.for(window);
|
var WindowEventDispatcher = EventDispatcher.for(window);
|
||||||
|
|
||||||
|
@ -1881,29 +1884,14 @@ var BrowserApp = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contentType === "tracking") {
|
if (data.contentType === "tracking") {
|
||||||
// Convert document URI into the format used by
|
|
||||||
// nsChannelClassifier::ShouldEnableTrackingProtection
|
|
||||||
// (any scheme turned into https is correct)
|
|
||||||
let normalizedUrl = Services.io.newURI("https://" + browser.currentURI.hostPort);
|
|
||||||
if (data.allowContent) {
|
if (data.allowContent) {
|
||||||
// Add the current host in the 'trackingprotection' consumer of
|
ContentBlockingAllowList.add(browser);
|
||||||
// the permission manager using a normalized URI. This effectively
|
if (!PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
||||||
// places this host on the tracking protection white list.
|
|
||||||
if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
|
||||||
PrivateBrowsingUtils.addToTrackingAllowlist(normalizedUrl);
|
|
||||||
} else {
|
|
||||||
Services.perms.addFromPrincipal(browser.contentPrincipal, "trackingprotection", Services.perms.ALLOW_ACTION);
|
|
||||||
Telemetry.addData("TRACKING_PROTECTION_EVENTS", 1);
|
Telemetry.addData("TRACKING_PROTECTION_EVENTS", 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove the current host from the 'trackingprotection' consumer
|
ContentBlockingAllowList.remove(browser);
|
||||||
// of the permission manager. This effectively removes this host
|
if (!PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
||||||
// from the tracking protection white list (any list actually).
|
|
||||||
// eslint-disable-next-line no-lonely-if
|
|
||||||
if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
|
||||||
PrivateBrowsingUtils.removeFromTrackingAllowlist(normalizedUrl);
|
|
||||||
} else {
|
|
||||||
Services.perms.removeFromPrincipal(browser.contentPrincipal, "trackingprotection");
|
|
||||||
Telemetry.addData("TRACKING_PROTECTION_EVENTS", 2);
|
Telemetry.addData("TRACKING_PROTECTION_EVENTS", 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = [ "ContentBlockingAllowList" ];
|
||||||
|
|
||||||
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||||
|
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper module to manage the Content Blocking Allow List.
|
||||||
|
*
|
||||||
|
* This module provides a couple of utility APIs for adding or
|
||||||
|
* removing a given browser object to the Content Blocking allow
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
const ContentBlockingAllowList = {
|
||||||
|
_observingLastPBContext: false,
|
||||||
|
|
||||||
|
_maybeSetupLastPBContextObserver() {
|
||||||
|
if (!this._observingLastPBContext) {
|
||||||
|
this._observer = {
|
||||||
|
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||||
|
|
||||||
|
observe(subject, topic, data) {
|
||||||
|
if (topic == "last-pb-context-exited") {
|
||||||
|
Services.perms.removeByType("trackingprotection-pb");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Services.obs.addObserver(this._observer, "last-pb-context-exited", true);
|
||||||
|
this._observingLastPBContext = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_baseURIForAntiTrackingCommon(browser) {
|
||||||
|
// Convert document URI into the format used by
|
||||||
|
// AntiTrackingCommon::IsOnContentBlockingAllowList.
|
||||||
|
// Any scheme turned into https is correct.
|
||||||
|
try {
|
||||||
|
return Services.io.newURI("https://" + browser.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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_basePrincipalForAntiTrackingCommon(browser) {
|
||||||
|
let baseURI = this._baseURIForAntiTrackingCommon(browser);
|
||||||
|
if (!baseURI) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let attrs = browser.contentPrincipal.originAttributes;
|
||||||
|
return Services.scriptSecurityManager
|
||||||
|
.createCodebasePrincipal(baseURI, attrs);
|
||||||
|
},
|
||||||
|
|
||||||
|
_permissionTypeFor(browser) {
|
||||||
|
return PrivateBrowsingUtils.isBrowserPrivate(browser) ?
|
||||||
|
"trackingprotection-pb" :
|
||||||
|
"trackingprotection";
|
||||||
|
},
|
||||||
|
|
||||||
|
_expiryFor(browser) {
|
||||||
|
return PrivateBrowsingUtils.isBrowserPrivate(browser) ?
|
||||||
|
Ci.nsIPermissionManager.EXPIRE_SESSION :
|
||||||
|
Ci.nsIPermissionManager.EXPIRE_NEVER;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if this module cannot handle the current document loaded in
|
||||||
|
* the browser object. This can happen for example for about: or file:
|
||||||
|
* documents.
|
||||||
|
*/
|
||||||
|
canHandle(browser) {
|
||||||
|
return this._basePrincipalForAntiTrackingCommon(browser) != null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given browser object to the Content Blocking allow list.
|
||||||
|
*/
|
||||||
|
add(browser) {
|
||||||
|
// Start observing PB last-context-exit notification to do the needed cleanup.
|
||||||
|
this._maybeSetupLastPBContextObserver();
|
||||||
|
|
||||||
|
let prin = this._basePrincipalForAntiTrackingCommon(browser);
|
||||||
|
let type = this._permissionTypeFor(browser);
|
||||||
|
let expire = this._expiryFor(browser);
|
||||||
|
Services.perms.addFromPrincipal(prin, type,
|
||||||
|
Services.perms.ALLOW_ACTION,
|
||||||
|
expire);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given browser object from the Content Blocking allow list.
|
||||||
|
*/
|
||||||
|
remove(browser) {
|
||||||
|
let prin = this._basePrincipalForAntiTrackingCommon(browser);
|
||||||
|
let type = this._permissionTypeFor(browser);
|
||||||
|
Services.perms.removeFromPrincipal(prin, type);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the current browser has loaded a document that is on the
|
||||||
|
* Content Blocking allow list.
|
||||||
|
*/
|
||||||
|
includes(browser) {
|
||||||
|
let prin = this._basePrincipalForAntiTrackingCommon(browser);
|
||||||
|
let type = this._permissionTypeFor(browser);
|
||||||
|
return Services.perms.testExactPermissionFromPrincipal(prin, type) ==
|
||||||
|
Services.perms.ALLOW_ACTION;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -33,6 +33,10 @@ UNIFIED_SOURCES += [
|
||||||
'StoragePrincipalHelper.cpp',
|
'StoragePrincipalHelper.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
EXTRA_JS_MODULES += [
|
||||||
|
'ContentBlockingAllowList.jsm',
|
||||||
|
]
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'/extensions/permissions',
|
'/extensions/permissions',
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,41 +6,6 @@ var EXPORTED_SYMBOLS = ["PrivateBrowsingUtils"];
|
||||||
|
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function PrivateBrowsingContentBlockingAllowList() {
|
|
||||||
Services.obs.addObserver(this, "last-pb-context-exited", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
PrivateBrowsingContentBlockingAllowList.prototype = {
|
|
||||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the provided URI to the list of allowed tracking sites.
|
|
||||||
*
|
|
||||||
* @param uri nsIURI
|
|
||||||
* The URI to add to the list.
|
|
||||||
*/
|
|
||||||
addToAllowList(uri) {
|
|
||||||
Services.perms.add(uri, "trackingprotection-pb", Ci.nsIPermissionManager.ALLOW_ACTION,
|
|
||||||
Ci.nsIPermissionManager.EXPIRE_SESSION);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the provided URI from the list of allowed tracking sites.
|
|
||||||
*
|
|
||||||
* @param uri nsIURI
|
|
||||||
* The URI to remove from the list.
|
|
||||||
*/
|
|
||||||
removeFromAllowList(uri) {
|
|
||||||
Services.perms.remove(uri, "trackingprotection-pb");
|
|
||||||
},
|
|
||||||
|
|
||||||
observe(subject, topic, data) {
|
|
||||||
if (topic == "last-pb-context-exited") {
|
|
||||||
Services.perms.removeByType("trackingprotection-pb");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const kAutoStartPref = "browser.privatebrowsing.autostart";
|
const kAutoStartPref = "browser.privatebrowsing.autostart";
|
||||||
|
|
||||||
// This will be set to true when the PB mode is autostarted from the command
|
// This will be set to true when the PB mode is autostarted from the command
|
||||||
|
@ -86,19 +51,6 @@ var PrivateBrowsingUtils = {
|
||||||
return aWindow.docShell.QueryInterface(Ci.nsILoadContext);
|
return aWindow.docShell.QueryInterface(Ci.nsILoadContext);
|
||||||
},
|
},
|
||||||
|
|
||||||
get _pbCBAllowList() {
|
|
||||||
delete this._pbCBAllowList;
|
|
||||||
return this._pbCBAllowList = new PrivateBrowsingContentBlockingAllowList();
|
|
||||||
},
|
|
||||||
|
|
||||||
addToTrackingAllowlist(aURI) {
|
|
||||||
this._pbCBAllowList.addToAllowList(aURI);
|
|
||||||
},
|
|
||||||
|
|
||||||
removeFromTrackingAllowlist(aURI) {
|
|
||||||
this._pbCBAllowList.removeFromAllowList(aURI);
|
|
||||||
},
|
|
||||||
|
|
||||||
get permanentPrivateBrowsing() {
|
get permanentPrivateBrowsing() {
|
||||||
try {
|
try {
|
||||||
return gTemporaryAutoStartMode ||
|
return gTemporaryAutoStartMode ||
|
||||||
|
|
Загрузка…
Ссылка в новой задаче