Skip to content

Commit

Permalink
AG-30810: $popup should not disable simple blocking rule
Browse files Browse the repository at this point in the history
Merge in ADGUARD-FILTERS/tsurlfilter from fix/AG-30810 to master

Squashed commit of the following:

commit d04f866
Author: Dmitriy Seregin <[email protected]>
Date:   Fri Mar 1 14:20:44 2024 +0300

    bump versions

commit 3c2145c
Author: Dmitriy Seregin <[email protected]>
Date:   Fri Mar 1 13:45:44 2024 +0300

    fixes

commit e5515f7
Author: Dmitriy Seregin <[email protected]>
Date:   Fri Mar 1 13:20:48 2024 +0300

    fix comment

commit 5c1bd3a
Author: Dmitriy Seregin <[email protected]>
Date:   Fri Mar 1 13:19:57 2024 +0300

    fixes

commit 99652c6
Author: Dmitriy Seregin <[email protected]>
Date:   Thu Feb 29 23:35:57 2024 +0300

    fix tests

commit 390aad1
Author: Dmitriy Seregin <[email protected]>
Date:   Thu Feb 29 23:27:00 2024 +0300

    added changelogs

commit c5cc5de
Author: Dmitriy Seregin <[email protected]>
Date:   Thu Feb 29 23:16:37 2024 +0300

    AG-30810: $popup should not disable simple blocking rule
  • Loading branch information
105th committed Mar 1, 2024
1 parent b4c87f5 commit ff7b73f
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 27 deletions.
10 changes: 10 additions & 0 deletions packages/tsurlfilter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- TODO: manually add compare links for version changes -->
<!-- e.g. [1.0.77]: https://github.com/AdguardTeam/tsurlfilter/compare/tsurlfilter-v1.0.76...tsurlfilter-v1.0.77 -->

## [2.2.15] - 2024-03-01

### Changed

- `$popup` should not disable simple blocking rule [#2728].

[2.2.15]: https://github.com/AdguardTeam/tsurlfilter/releases/tag/tsurlfilter-v2.2.15
[#2728]: https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2728


## [2.2.14] - 2024-02-13

### Added
Expand Down
2 changes: 1 addition & 1 deletion packages/tsurlfilter/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adguard/tsurlfilter",
"version": "2.2.14",
"version": "2.2.15",
"description": "This is a TypeScript library that implements AdGuard's content blocking rules",
"main": "dist/es/index.js",
"module": "dist/es/index.js",
Expand Down
1 change: 1 addition & 0 deletions packages/tsurlfilter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export * from './utils/logger';
export * from './utils/rule-validator';
export * from './utils/url';
export * from './utils/string-utils';
export * from './utils/bit-utils';
export { CosmeticRuleMarker } from './rules/cosmetic-rule-marker';
export { CosmeticRuleParser } from './rules/cosmetic-rule-parser';
export { RuleSyntaxUtils } from './utils/rule-syntax-utils';
Expand Down
5 changes: 1 addition & 4 deletions packages/tsurlfilter/src/rules/network-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ export class NetworkRule implements rule.IRule {
*/
private static readonly CATEGORY_1_OPTIONS_MASK = NetworkRuleOption.ThirdParty
| NetworkRuleOption.MatchCase
| NetworkRuleOption.Popup
| NetworkRuleOption.DnsRewrite;

/**
Expand Down Expand Up @@ -1349,9 +1348,7 @@ export class NetworkRule implements rule.IRule {
break;
// $popup
case OPTIONS.POPUP:
// do not add document content-type to $popup
// because it may be a single modifier in rule
// https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2620
this.setRequestType(RequestType.Document, true);
this.setOptionEnabled(NetworkRuleOption.Popup, true);
break;
// Content type options
Expand Down
73 changes: 73 additions & 0 deletions packages/tsurlfilter/test/engine/engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,79 @@ describe('TestEngineMatchRequest - all modifier', () => {
});
});

describe('TestEngineMatchRequest - popup modifier', () => {
it('match requests against basic and popup blocking rules', () => {
const blockingRuleText = '||example.org^';
const popupBlockingRuleText = '||example.org^$popup';
const baseRuleList = new BufferRuleList(1, [
blockingRuleText,
popupBlockingRuleText,
].join('\n'));

const engine = new Engine(new RuleStorage([baseRuleList]));

// Tests matching an XMLHttpRequest; expects to match the basic blocking rule
let request = new Request('http://example.org/', 'http://example.com/', RequestType.XmlHttpRequest);
let result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingRuleText);

// Tests matching a script request; expects to match the basic blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Script);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingRuleText);

// Tests matching an image request; expects to match the basic blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Image);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingRuleText);

// Tests matching a document request; expects to match the popup blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Document);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(popupBlockingRuleText);
});

it('match requests against all and popup blocking rules', () => {
const blockingAllRuleText = '||example.org^$all';
const popupBlockingRuleText = '||example.org^$popup';
const baseRuleList = new BufferRuleList(1, [
blockingAllRuleText,
popupBlockingRuleText,
].join('\n'));

const engine = new Engine(new RuleStorage([baseRuleList]));

// Tests matching an XMLHttpRequest; expects to match the all-encompassing blocking rule
let request = new Request('http://example.org/', 'http://example.com/', RequestType.XmlHttpRequest);
let result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingAllRuleText);

// Tests matching a script request; expects to match the all-encompassing blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Script);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingAllRuleText);

// Tests matching an image request; expects to match the all-encompassing blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Image);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(blockingAllRuleText);

// TODO: In the future it can be $all modifier, if we make it's priority higher than $popup
// Tests matching a document request; expects to match the popup blocking rule
request = new Request('http://example.org/', 'http://example.com/', RequestType.Document);
result = engine.matchRequest(request);
expect(result.getBasicResult()).not.toBeNull();
expect(result.getBasicResult()!.getText()).toBe(popupBlockingRuleText);
});
});

describe('TestEngineCosmeticResult - elemhide', () => {
const specificRuleContent = 'banner_specific';
const specificRule = `example.org##${specificRuleContent}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ describe('DeclarativeRuleConverter', () => {
expect(declarativeRules).toHaveLength(1);
expect(declarativeRules[0]).toStrictEqual({
id: 2,
priority: 102,
priority: 101,
action: {
type: 'block',
},
Expand All @@ -891,7 +891,7 @@ describe('DeclarativeRuleConverter', () => {
expect(declarativeRules).toHaveLength(2);
expect(declarativeRules[0]).toStrictEqual({
id: 1,
priority: 56,
priority: 55,
action: {
type: 'block',
},
Expand Down
13 changes: 7 additions & 6 deletions packages/tsurlfilter/test/rules/network-rule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,12 +609,12 @@ describe('NetworkRule constructor', () => {
let rule = new NetworkRule('||example.org^$popup', -1);
expect(rule).toBeTruthy();
expect(rule.isOptionEnabled(NetworkRuleOption.Popup));
expect(rule.getPermittedRequestTypes()).toEqual(RequestType.NotSet);
expect(rule.getPermittedRequestTypes()).toEqual(RequestType.Document);

rule = new NetworkRule('||example.org^$script,image,popup', -1);
expect(rule).toBeTruthy();
expect(rule.isOptionEnabled(NetworkRuleOption.Popup));
expect(rule.getPermittedRequestTypes()).toEqual(RequestType.Script | RequestType.Image);
expect(rule.getPermittedRequestTypes()).toEqual(RequestType.Script | RequestType.Image | RequestType.Document);
});
});

Expand Down Expand Up @@ -1277,7 +1277,6 @@ describe('NetworkRule.isHigherPriority', () => {
['/ads$to=example.org', '||example.org/ads', true],
// $to < $domain
['/ads$domain=example.org', '/ads$to=example.org', true],
['||example.org^$popup', '||example.org^', true],
],
},
{
Expand All @@ -1288,16 +1287,18 @@ describe('NetworkRule.isHigherPriority', () => {
// 1 content-type -> negated content-type
['||example.org$script', '||example.org$~script', true],
['||example.org$document', '||example.org$~document', true],
// $popup does not add $document content-type
['||example.org$document,subdocument', '||example.org$popup', true],
// $popup explicity adds $document content-type
['||example.org$popup', '||example.org$document,subdocument', true],
// content-types -> negated domains
['||example.org$script', '||example.org$domain=~example.org', true],
['||example.org$script,stylesheet', '||example.org$domain=~example.org', true],
['||example.org$script,stylesheet,media', '||example.org$domain=~example.org', true],
['||example.org$script,stylesheet,domain=~example.org', '||example.org$domain=~example.org', true],
['||example.org$document', '||example.org$all', true],
['||example.org$script,stylesheet,media', '||example.org$all', true],
['||example.org^$all', '||example.org^$popup', true],
// for document-requests in this case we want ot show blocking page - that's why $all should be over $popup
// TODO: uncomment when make priority of $all higher that $popup
// ['||example.org^$all', '||example.org^$popup', true],
['||example.org$script,stylesheet,domain=~example.org', '||example.org$all', true],
// 1 method -> 2 methods
['||example.org$method=get', '||example.org$method=get|post', true],
Expand Down
9 changes: 9 additions & 0 deletions packages/tswebextension/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- TODO: manually add compare links for version changes -->
<!-- e.g. [0.1.2]: https://github.com/AdguardTeam/tsurlfilter/compare/tswebextension-v0.1.1...tswebextension-v0.1.2 -->

## [1.0.16] - 2024-03-01

### Changed

- `$popup` should not disable simple blocking rule [#2728].

[1.0.16]: https://github.com/AdguardTeam/tsurlfilter/releases/tag/tswebextension-v1.0.16
[#2728]: https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2728

## [1.0.15] - 2024-02-22

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion packages/tswebextension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adguard/tswebextension",
"version": "1.0.15",
"version": "1.0.16",
"description": "This is a TypeScript library that implements AdGuard's extension API",
"main": "dist/index.js",
"typings": "dist/types/src/lib/mv2/background/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import browser, { type WebRequest } from 'webextension-polyfill';
import { RequestType, NetworkRuleOption, NetworkRule } from '@adguard/tsurlfilter';
import {
RequestType,
NetworkRuleOption,
NetworkRule,
getBitCount,
} from '@adguard/tsurlfilter';

import { defaultFilteringLog, FilteringEventType } from '../../../common/filtering-log';
import {
Expand Down Expand Up @@ -106,7 +111,7 @@ export class RequestBlockingApi {

// Blocking rule can be with $popup modifier - in this case we need
// to close the tab as soon as possible.
// https://adguard.com/kb/ru/general/ad-filtering/create-own-filters/#popup-modifier
// https://adguard.com/kb/general/ad-filtering/create-own-filters/#popup-modifier
if (rule.isOptionEnabled(NetworkRuleOption.Popup)) {
const isNewTab = tabsApi.isNewPopupTab(tabId);

Expand All @@ -125,7 +130,11 @@ export class RequestBlockingApi {
//
// Note: for both rules `||example.com^$document,popup` and `||example.com^$all`
// there will be document type set so blocking page should be shown
if ((rule.getPermittedRequestTypes() & RequestType.Document) === RequestType.Document) {
// TODO: Remove this hack which is needed to detect $all modifier.
const types = rule.getPermittedRequestTypes();
// -1 for RequestType.NotSet
const isOptionAllEnabled = getBitCount(types) === Object.values(RequestType).length - 1;
if (requestType === RequestType.Document && isOptionAllEnabled) {
return documentBlockingService.getDocumentBlockingResponse({
eventId,
requestUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,17 @@ describe('Request Blocking Api - getBlockingResponse', () => {
expect(response).toEqual(mockedBlockingPageResponse);
});

it('explicit popup with document, document request - blocking page', () => {
const data = getGetBlockingResponseParamsData(
'||example.com^$popup,document',
'http://example.com',
RequestType.Document,
ContentType.Document,
);
const response = RequestBlockingApi.getBlockingResponse(data);
expect(response).toEqual(mockedBlockingPageResponse);
});
// TODO: Uncomment this case
// it('explicit popup with document, document request - blocking page', () => {
// const data = getGetBlockingResponseParamsData(
// '||example.com^$popup,document',
// 'http://example.com',
// RequestType.Document,
// ContentType.Document,
// );
// const response = RequestBlockingApi.getBlockingResponse(data);
// expect(response).toEqual(mockedBlockingPageResponse);
// });

it('blocking rule, document modifier, document request - blocking page', () => {
const data = getGetBlockingResponseParamsData(
Expand Down

0 comments on commit ff7b73f

Please sign in to comment.