Skip to content

Commit

Permalink
https://github.com/adguardteam/adguardbrowserextension/issues/685
Browse files Browse the repository at this point in the history
  • Loading branch information
atropnikov committed May 15, 2017
1 parent b7e2d46 commit 577b829
Show file tree
Hide file tree
Showing 18 changed files with 397 additions and 46 deletions.
1 change: 1 addition & 0 deletions Extension/api/chrome/background.html
Expand Up @@ -48,6 +48,7 @@
<script type="text/javascript" src="lib/filter/rules/script-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter-rule.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/csp-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/filter-rule-builder.js"></script>

<!--Filters metadata and filtration modules-->
Expand Down
1 change: 1 addition & 0 deletions Extension/browser/chrome/background.html
Expand Up @@ -49,6 +49,7 @@
<script type="text/javascript" src="lib/filter/rules/script-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter-rule.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/csp-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/filter-rule-builder.js"></script>

<!--Filters metadata and filtration modules-->
Expand Down
1 change: 1 addition & 0 deletions Extension/browser/firefox/background.html
Expand Up @@ -53,6 +53,7 @@
<script type="text/javascript" src="lib/filter/rules/script-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter-rule.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/csp-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/filter-rule-builder.js"></script>

<!--Filters metadata and filtration modules-->
Expand Down
1 change: 1 addition & 0 deletions Extension/browser/firefox_webext/background.html
Expand Up @@ -49,6 +49,7 @@
<script type="text/javascript" src="lib/filter/rules/script-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter-rule.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/csp-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/filter-rule-builder.js"></script>

<!--Filters metadata and filtration modules-->
Expand Down
1 change: 1 addition & 0 deletions Extension/browser/safari/background.html
Expand Up @@ -48,6 +48,7 @@
<script type="text/javascript" src="lib/filter/rules/script-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter-rule.js"></script>
<script type="text/javascript" src="lib/filter/rules/url-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/csp-filter.js"></script>
<script type="text/javascript" src="lib/filter/rules/filter-rule-builder.js"></script>

<!--Filters metadata and filtration modules-->
Expand Down
10 changes: 6 additions & 4 deletions Extension/browser/safari/lib/converter.js
Expand Up @@ -160,15 +160,17 @@ var SafariContentBlockerConverter = {

// Not supported modificators
if (this._isContentType(rule, UrlFilterRule.contentTypes.OBJECT)) {
throw new Error('Object content type is not yet supported');
throw new Error('$object content type is not yet supported');
}
if (this._isContentType(rule, UrlFilterRule.contentTypes['OBJECT-SUBREQUEST'])) {
throw new Error('Object_subrequest content type is not yet supported');
throw new Error('$object_subrequest content type is not yet supported');
}
if (this._isContentType(rule, UrlFilterRule.contentTypes.WEBRTC)) {
throw new Error('WebRTC content type is not yet supported');
throw new Error('$webrtc content type is not yet supported');
}
if (this._isContentType(rule, UrlFilterRule.contentTypes.CSP)) {
throw new Error('$csp content type is not yet supported');
}

if (this._isContentType(rule, UrlFilterRule.contentTypes.JSINJECT)) {
throw new Error('$jsinject rules are ignored.');
}
Expand Down
5 changes: 5 additions & 0 deletions Extension/lib/filter/antibanner.js
Expand Up @@ -1196,6 +1196,10 @@ adguard.requestFilter = (function (adguard) {
return getRequestFilter().getScriptsForUrl(documentUrl);
};

var getCspRules = function (requestUrl, referrer) {
return getRequestFilter().findCspRules(requestUrl, referrer);
};

var getRequestFilterInfo = function () {
return antiBannerService.getRequestFilterInfo();
};
Expand All @@ -1218,6 +1222,7 @@ adguard.requestFilter = (function (adguard) {
getSelectorsForUrl: getSelectorsForUrl,
getInjectedSelectorsForUrl: getInjectedSelectorsForUrl,
getScriptsForUrl: getScriptsForUrl,
getCspRules: getCspRules,

getRequestFilterInfo: getRequestFilterInfo,
updateContentBlockerInfo: updateContentBlockerInfo,
Expand Down
39 changes: 33 additions & 6 deletions Extension/lib/filter/filters.js
Expand Up @@ -43,6 +43,10 @@
// JS injection rules: http://adguard.com/en/filterrules.html#javascriptInjection
this.scriptFilter = new adguard.rules.ScriptFilter();

// Filter that applies CSP rules
// CSP rules: TODO: add link
this.cspFilter = new adguard.rules.CspFilter();

// Rules count (includes all types of rules)
this.rulesCount = 0;

Expand Down Expand Up @@ -85,10 +89,14 @@
return;
}
if (rule instanceof adguard.rules.UrlFilterRule) {
if (rule.whiteListRule) {
this.urlWhiteFilter.addRule(rule);
if (rule.cspRule) {
this.cspFilter.addRule(rule);
} else {
this.urlBlockingFilter.addRule(rule);
if (rule.whiteListRule) {
this.urlWhiteFilter.addRule(rule);
} else {
this.urlBlockingFilter.addRule(rule);
}
}
} else if (rule instanceof adguard.rules.CssFilterRule) {
this.cssFilter.addRule(rule);
Expand All @@ -111,10 +119,14 @@
return;
}
if (rule instanceof adguard.rules.UrlFilterRule) {
if (rule.whiteListRule) {
this.urlWhiteFilter.removeRule(rule);
if (rule.cspRule) {
this.cspFilter.removeRule(rule);
} else {
this.urlBlockingFilter.removeRule(rule);
if (rule.whiteListRule) {
this.urlWhiteFilter.removeRule(rule);
} else {
this.urlBlockingFilter.removeRule(rule);
}
}
} else if (rule instanceof adguard.rules.CssFilterRule) {
this.cssFilter.removeRule(rule);
Expand All @@ -135,6 +147,7 @@
result = result.concat(this.urlBlockingFilter.getRules());
result = result.concat(this.cssFilter.getRules());
result = result.concat(this.scriptFilter.getRules());
result = result.concat(this.cspFilter.getRules());

return result;
},
Expand Down Expand Up @@ -250,6 +263,20 @@
return rule;
},

/**
* Searches for CSP rules for the specified request
* @param requestUrl Request URL
* @param documentUrl Document URL
* @returns Collection of CSP rules for applying to the request or null
*/
findCspRules: function (requestUrl, documentUrl) {

var documentHost = adguard.utils.url.getHost(documentUrl);
var thirdParty = adguard.utils.url.isThirdPartyRequest(requestUrl, documentUrl);

return this.cspFilter.findCspRules(requestUrl, documentHost, thirdParty);
},

/**
* Checks if exception rule is present for the URL/Referrer pair
*
Expand Down
23 changes: 23 additions & 0 deletions Extension/lib/filter/request-blocking.js
Expand Up @@ -251,6 +251,28 @@ adguard.webRequestService = (function (adguard) {
return adguard.requestFilter.findRuleForRequest(requestUrl, referrerUrl, requestType, whitelistRule);
};

/**
* Find CSP rules for request
* @param tab Tab
* @param requestUrl Request URL
* @param referrerUrl Referrer URL
* @returns {*} Collection of rules or null
*/
var getCspRules = function (tab, requestUrl, referrerUrl) {

if (adguard.frames.isTabAdguardDetected(tab) || adguard.frames.isTabProtectionDisabled(tab) || adguard.frames.isTabWhiteListed(tab)) {
//don't process request
return null;
}

var whitelistRule = adguard.requestFilter.findWhiteListRule(requestUrl, referrerUrl, adguard.RequestTypes.DOCUMENT);
if (whitelistRule && whitelistRule.checkContentTypeIncluded("DOCUMENT")) {
return null;
}

return adguard.requestFilter.getCspRules(requestUrl, referrerUrl);
};

/**
* Processes HTTP response.
* It could do the following:
Expand Down Expand Up @@ -364,6 +386,7 @@ adguard.webRequestService = (function (adguard) {
isRequestBlockedByRule: isRequestBlockedByRule,
getBlockedResponseByRule: getBlockedResponseByRule,
getRuleForRequest: getRuleForRequest,
getCspRules: getCspRules,
processRequestResponse: processRequestResponse,
postProcessRequest: postProcessRequest,
onRequestBlocked: onRequestBlockedChannel
Expand Down
130 changes: 130 additions & 0 deletions Extension/lib/filter/rules/csp-filter.js
@@ -0,0 +1,130 @@
/**
* This file is part of Adguard Browser Extension (https://github.com/AdguardTeam/AdguardBrowserExtension).
*
* Adguard Browser Extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Adguard Browser Extension is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Adguard Browser Extension. If not, see <http://www.gnu.org/licenses/>.
*/
(function (adguard, api) {

'use strict';

/**
* Filter for CSP filter rules
* https://github.com/AdguardTeam/AdguardBrowserExtension/issues/685
*/
api.CspFilter = function (rules) {

var cspWhiteFilter = new api.UrlFilterRuleLookupTable();
var cspBlockFilter = new api.UrlFilterRuleLookupTable();

/**
* Add rules to CSP filter
* @param rules Collection of $csp rules
*/
function addRules(rules) {
for (var i = 0; i < rules.length; i++) {
addRule(rules[i]);
}
}

/**
* Add rule to CSP filter
* @param rule Rule object
*/
function addRule(rule) {
if (rule.whiteListRule) {
cspWhiteFilter.addRule(rule);
} else {
cspBlockFilter.addRule(rule);
}
}

/**
* Removes from CSP filter
* @param rule Rule to remove
*/
function removeRule(rule) {
if (rule.whiteListRule) {
cspWhiteFilter.removeRule(rule);
} else {
cspBlockFilter.removeRule(rule);
}
}

function getRules() {
var rules = cspWhiteFilter.getRules();
return rules.concat(cspBlockFilter.getRules());
}

/**
* Searches for rules matching specified request.
* It worth noting that rules will be filtered by whitelist $csp rules.
* @param url URL
* @param documentHost Document Host
* @param thirdParty true if request is third-party
* @returns Matching rules
*/
function findCspRules(url, documentHost, thirdParty) {

var i, rule;

var whiteRules = cspWhiteFilter.findRules(url, documentHost, thirdParty, adguard.RequestTypes.CSP);

var whitelisted = Object.create(null);

// Collect whitelisted CSP directives
if (whiteRules) {
for (i = 0; i < whiteRules.length; i++) {
rule = whiteRules[i];
if (!rule.cspDirective) { // Global whitelist rule
return null;
}
whitelisted[rule.cspDirective] = true;
}
}

var cspRules = null;

var blockingRules = cspBlockFilter.findRules(url, documentHost, thirdParty, adguard.RequestTypes.CSP);

// Collect blocking CSP directives which aren't in whitelist
if (blockingRules) {
for (i = 0; i < blockingRules.length; i++) {
rule = blockingRules[i];
if (rule.cspDirective in whitelisted) {
continue;
}
if (cspRules === null) {
cspRules = [];
}
cspRules.push(rule);
}
}

return cspRules;
}

if (rules) {
addRules(rules);
}

return {
addRules: addRules,
addRule: addRule,
removeRule: removeRule,
getRules: getRules,
findCspRules: findCspRules
};
};

})(adguard, adguard.rules);

0 comments on commit 577b829

Please sign in to comment.