mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1429178 - Policy: Implement website blocklist/allowlist. r=mixedpuppy
MozReview-Commit-ID: EAX0VwxlggK --HG-- extra : rebase_source : d795b96a0318e7b2bb21bf24c15413111628aa73
This commit is contained in:
parent
043bf247e7
commit
7d1da2c7e5
@ -11,10 +11,11 @@ XPCOMUtils.defineLazyServiceGetter(this, "gXulStore",
|
||||
"nsIXULStore");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
BookmarksPolicies: "resource:///modules/policies/BookmarksPolicies.jsm",
|
||||
ProxyPolicies: "resource:///modules/policies/ProxyPolicies.jsm",
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
BookmarksPolicies: "resource:///modules/policies/BookmarksPolicies.jsm",
|
||||
CustomizableUI: "resource:///modules/CustomizableUI.jsm",
|
||||
ProxyPolicies: "resource:///modules/policies/ProxyPolicies.jsm",
|
||||
WebsiteFilter: "resource:///modules/policies/WebsiteFilter.jsm",
|
||||
});
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
@ -579,7 +580,14 @@ var Policies = {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"WebsiteFilter": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
this.filter = new WebsiteFilter(param.Block || [], param.Exceptions || []);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
108
browser/components/enterprisepolicies/helpers/WebsiteFilter.jsm
Normal file
108
browser/components/enterprisepolicies/helpers/WebsiteFilter.jsm
Normal file
@ -0,0 +1,108 @@
|
||||
/* 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";
|
||||
|
||||
/*
|
||||
* This module implements the policy to block websites from being visited,
|
||||
* or to only allow certain websites to be visited.
|
||||
*
|
||||
* The blocklist takes as input an array of MatchPattern strings, as documented
|
||||
* at https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns.
|
||||
*
|
||||
* The exceptions list takes the same as input. This list opens up
|
||||
* exceptions for rules on the blocklist that might be too strict.
|
||||
*
|
||||
* In addition to that, this allows the user to create a whitelist approach,
|
||||
* by using the special "<all_urls>" pattern for the blocklist, and then
|
||||
* adding all whitelisted websites on the exceptions list.
|
||||
*
|
||||
* Note that this module only blocks top-level website navigations. It doesn't
|
||||
* block any other accesses to these urls: image tags, scripts, XHR, etc.,
|
||||
* because that could cause unexpected breakage. This is a policy to block
|
||||
* users from visiting certain websites, and not from blocking any network
|
||||
* connections to those websites. If the admin is looking for that, the recommended
|
||||
* way is to configure that with extensions or through a company firewall.
|
||||
*/
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const LIST_LENGTH_LIMIT = 1000;
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "WebsiteFilter Policy",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "WebsiteFilter" ];
|
||||
|
||||
function WebsiteFilter(blocklist, exceptionlist) {
|
||||
let blockArray = [], exceptionArray = [];
|
||||
|
||||
for (let i = 0; i < blocklist.length && i < LIST_LENGTH_LIMIT; i++) {
|
||||
try {
|
||||
let pattern = new MatchPattern(blocklist[i]);
|
||||
blockArray.push(pattern);
|
||||
log.debug(`Pattern added to WebsiteFilter.Block list: ${blocklist[i]}`);
|
||||
} catch (e) {
|
||||
log.error(`Invalid pattern on WebsiteFilter.Block: ${blocklist[i]}`);
|
||||
}
|
||||
}
|
||||
|
||||
this._blockPatterns = new MatchPatternSet(blockArray);
|
||||
|
||||
for (let i = 0; i < exceptionlist.length && i < LIST_LENGTH_LIMIT; i++) {
|
||||
try {
|
||||
let pattern = new MatchPattern(exceptionlist[i]);
|
||||
exceptionArray.push(pattern);
|
||||
log.debug(`Pattern added to WebsiteFilter.Exceptions list: ${exceptionlist[i]}`);
|
||||
} catch (e) {
|
||||
log.error(`Invalid pattern on WebsiteFilter.Exceptions: ${exceptionlist[i]}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionArray.length) {
|
||||
this._exceptionsPatterns = new MatchPatternSet(exceptionArray);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "http-on-modify-request", true);
|
||||
}
|
||||
|
||||
WebsiteFilter.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
observe(subject, topic, data) {
|
||||
let channel, isDocument = false;
|
||||
try {
|
||||
channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
||||
isDocument = channel.isDocument;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only filter document accesses
|
||||
if (!isDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._blockPatterns.matches(channel.URI)) {
|
||||
if (!this._exceptionsPatterns ||
|
||||
!this._exceptionsPatterns.matches(channel.URI)) {
|
||||
// NS_ERROR_BLOCKED_BY_POLICY displays the error message
|
||||
// designed for policy-related blocks.
|
||||
channel.cancel(Cr.NS_ERROR_BLOCKED_BY_POLICY);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -10,4 +10,5 @@ with Files("**"):
|
||||
EXTRA_JS_MODULES.policies += [
|
||||
'BookmarksPolicies.jsm',
|
||||
'ProxyPolicies.jsm',
|
||||
'WebsiteFilter.jsm',
|
||||
]
|
||||
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"policies": {
|
||||
"WebsiteFilter": {
|
||||
"Block": [
|
||||
"*://*.mozilla.org/*",
|
||||
"invalid_pattern"
|
||||
],
|
||||
|
||||
"Exceptions": [
|
||||
"*://*.mozilla.org/*about*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -492,6 +492,29 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"WebsiteFilter": {
|
||||
"description": "Blocks websites from being visited. The parameters take an array of Match Patterns, as documented in https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns. Only http/https accesses are supported at the moment. The arrays are limited to 1000 entries each.",
|
||||
"first_available": "60.0",
|
||||
"enterprise_only": "true",
|
||||
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Block": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
|
||||
"Exceptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ support-files =
|
||||
opensearch.html
|
||||
opensearchEngine.xml
|
||||
policytest.xpi
|
||||
policy_websitefilter_block.html
|
||||
policy_websitefilter_exception.html
|
||||
|
||||
[browser_policies_basic_tests.js]
|
||||
[browser_policies_broken_json.js]
|
||||
@ -45,3 +47,4 @@ support-files =
|
||||
[browser_policy_search_engine.js]
|
||||
[browser_policy_searchbar.js]
|
||||
[browser_policy_set_homepage.js]
|
||||
[browser_policy_websitefilter.js]
|
||||
|
@ -0,0 +1,25 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const SUPPORT_FILES_PATH = "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser";
|
||||
const BLOCKED_PAGE = `${SUPPORT_FILES_PATH}/policy_websitefilter_block.html`;
|
||||
const EXCEPTION_PAGE = `${SUPPORT_FILES_PATH}/policy_websitefilter_exception.html`;
|
||||
|
||||
add_task(async function test() {
|
||||
await setupPolicyEngineWithJson({
|
||||
"policies": {
|
||||
"WebsiteFilter": {
|
||||
"Block": [
|
||||
"*://mochi.test/*policy_websitefilter_*"
|
||||
],
|
||||
"Exceptions": [
|
||||
"*://mochi.test/*_websitefilter_exception*"
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await checkBlockedPage(BLOCKED_PAGE, true);
|
||||
await checkBlockedPage(EXCEPTION_PAGE, false);
|
||||
});
|
@ -28,6 +28,23 @@ function checkUnlockedPref(prefName, prefValue) {
|
||||
EnterprisePolicyTesting.checkPolicyPref(prefName, prefValue, false);
|
||||
}
|
||||
|
||||
// Checks that a page was blocked by seeing if it was replaced with about:neterror
|
||||
async function checkBlockedPage(url, expectedBlocked) {
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url,
|
||||
waitForLoad: false,
|
||||
waitForStateStop: true,
|
||||
}, async function() {
|
||||
await BrowserTestUtils.waitForCondition(async function() {
|
||||
let blocked = await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
|
||||
return content.document.documentURI.startsWith("about:neterror");
|
||||
});
|
||||
return blocked == expectedBlocked;
|
||||
}, `Page ${url} block was correct (expected=${expectedBlocked}).`);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function policies_headjs_startWithCleanSlate() {
|
||||
if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
|
||||
await setupPolicyEngineWithJson("");
|
||||
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>This page should be blocked</title>
|
||||
</head>
|
||||
<body>
|
||||
This page should not be seen.
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>This page should not be blocked</title>
|
||||
</head>
|
||||
<body>
|
||||
This page should be seen.
|
||||
</body>
|
||||
</html>
|
@ -157,6 +157,7 @@ XPC_MSG_DEF(NS_ERROR_REDIRECT_LOOP , "The request failed as a r
|
||||
XPC_MSG_DEF(NS_ERROR_UNSAFE_CONTENT_TYPE , "The request failed because the content type returned by the server was not a type expected by the channel")
|
||||
XPC_MSG_DEF(NS_ERROR_REMOTE_XUL , "Attempt to access remote XUL document that is not in website's whitelist")
|
||||
XPC_MSG_DEF(NS_ERROR_LOAD_SHOWED_ERRORPAGE , "The load caused an error page to be displayed.")
|
||||
XPC_MSG_DEF(NS_ERROR_BLOCKED_BY_POLICY , "The request was blocked by a policy set by the system administrator.")
|
||||
|
||||
XPC_MSG_DEF(NS_ERROR_FTP_LOGIN , "FTP error while logging in")
|
||||
XPC_MSG_DEF(NS_ERROR_FTP_CWD , "FTP error while changing directory")
|
||||
|
Loading…
Reference in New Issue
Block a user