Skip to content

Commit 1e7149f

Browse files
Release build 4.4.2 [ci release]
1 parent 2d62c87 commit 1e7149f

File tree

9 files changed

+86
-16
lines changed

9 files changed

+86
-16
lines changed

Sources/ContentScopeScripts/dist/contentScope.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5799,6 +5799,7 @@
57995799
let hiddenElements = new WeakMap();
58005800
let appliedRules = new Set();
58015801
let shouldInjectStyleTag = false;
5802+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
58025803

58035804
/**
58045805
* Hide DOM element if rule conditions met
@@ -5927,17 +5928,25 @@
59275928
});
59285929

59295930
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5930-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5931+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
59315932
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5933+
// query original node instead of parsedNode for img elements since heuristic relies
5934+
// on size of image elements
5935+
const imageElements = [...node.querySelectorAll('img,svg')];
59325936
// about:blank iframes don't count as content, return true if:
59335937
// - node doesn't contain any iframes
59345938
// - node contains iframes, all of which are hidden or have src='about:blank'
59355939
const noFramesWithContent = frameElements.every((frame) => {
59365940
return (frame.hidden || frame.src === 'about:blank')
59375941
});
5942+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5943+
// these should be treated as empty and hidden, but real images should not.
5944+
const visibleImages = imageElements.some((image) => {
5945+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5946+
});
59385947

59395948
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5940-
noFramesWithContent && mediaContent === null) {
5949+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
59415950
return true
59425951
}
59435952
return false
@@ -6077,6 +6086,7 @@
60776086
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
60786087
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
60796088
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6089+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
60806090

60816091
// determine whether strict hide rules should be injected as a style tag
60826092
if (shouldInjectStyleTag) {

build/android/contentScope.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5799,6 +5799,7 @@
57995799
let hiddenElements = new WeakMap();
58005800
let appliedRules = new Set();
58015801
let shouldInjectStyleTag = false;
5802+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
58025803

58035804
/**
58045805
* Hide DOM element if rule conditions met
@@ -5927,17 +5928,25 @@
59275928
});
59285929

59295930
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5930-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5931+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
59315932
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5933+
// query original node instead of parsedNode for img elements since heuristic relies
5934+
// on size of image elements
5935+
const imageElements = [...node.querySelectorAll('img,svg')];
59325936
// about:blank iframes don't count as content, return true if:
59335937
// - node doesn't contain any iframes
59345938
// - node contains iframes, all of which are hidden or have src='about:blank'
59355939
const noFramesWithContent = frameElements.every((frame) => {
59365940
return (frame.hidden || frame.src === 'about:blank')
59375941
});
5942+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5943+
// these should be treated as empty and hidden, but real images should not.
5944+
const visibleImages = imageElements.some((image) => {
5945+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5946+
});
59385947

59395948
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5940-
noFramesWithContent && mediaContent === null) {
5949+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
59415950
return true
59425951
}
59435952
return false
@@ -6077,6 +6086,7 @@
60776086
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
60786087
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
60796088
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6089+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
60806090

60816091
// determine whether strict hide rules should be injected as a style tag
60826092
if (shouldInjectStyleTag) {

build/chrome-mv3/inject.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5733,6 +5733,7 @@
57335733
let hiddenElements = new WeakMap();
57345734
let appliedRules = new Set();
57355735
let shouldInjectStyleTag = false;
5736+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
57365737

57375738
/**
57385739
* Hide DOM element if rule conditions met
@@ -5861,17 +5862,25 @@
58615862
});
58625863

58635864
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5864-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5865+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
58655866
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5867+
// query original node instead of parsedNode for img elements since heuristic relies
5868+
// on size of image elements
5869+
const imageElements = [...node.querySelectorAll('img,svg')];
58665870
// about:blank iframes don't count as content, return true if:
58675871
// - node doesn't contain any iframes
58685872
// - node contains iframes, all of which are hidden or have src='about:blank'
58695873
const noFramesWithContent = frameElements.every((frame) => {
58705874
return (frame.hidden || frame.src === 'about:blank')
58715875
});
5876+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5877+
// these should be treated as empty and hidden, but real images should not.
5878+
const visibleImages = imageElements.some((image) => {
5879+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5880+
});
58725881

58735882
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5874-
noFramesWithContent && mediaContent === null) {
5883+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
58755884
return true
58765885
}
58775886
return false
@@ -6011,6 +6020,7 @@
60116020
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
60126021
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
60136022
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6023+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
60146024

60156025
// determine whether strict hide rules should be injected as a style tag
60166026
if (shouldInjectStyleTag) {

build/chrome/inject.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/firefox/inject.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5809,6 +5809,7 @@
58095809
let hiddenElements = new WeakMap();
58105810
let appliedRules = new Set();
58115811
let shouldInjectStyleTag = false;
5812+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
58125813

58135814
/**
58145815
* Hide DOM element if rule conditions met
@@ -5937,17 +5938,25 @@
59375938
});
59385939

59395940
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5940-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5941+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
59415942
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5943+
// query original node instead of parsedNode for img elements since heuristic relies
5944+
// on size of image elements
5945+
const imageElements = [...node.querySelectorAll('img,svg')];
59425946
// about:blank iframes don't count as content, return true if:
59435947
// - node doesn't contain any iframes
59445948
// - node contains iframes, all of which are hidden or have src='about:blank'
59455949
const noFramesWithContent = frameElements.every((frame) => {
59465950
return (frame.hidden || frame.src === 'about:blank')
59475951
});
5952+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5953+
// these should be treated as empty and hidden, but real images should not.
5954+
const visibleImages = imageElements.some((image) => {
5955+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5956+
});
59485957

59495958
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5950-
noFramesWithContent && mediaContent === null) {
5959+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
59515960
return true
59525961
}
59535962
return false
@@ -6087,6 +6096,7 @@
60876096
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
60886097
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
60896098
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6099+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
60906100

60916101
// determine whether strict hide rules should be injected as a style tag
60926102
if (shouldInjectStyleTag) {

build/integration/contentScope.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5712,6 +5712,7 @@
57125712
let hiddenElements = new WeakMap();
57135713
let appliedRules = new Set();
57145714
let shouldInjectStyleTag = false;
5715+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
57155716

57165717
/**
57175718
* Hide DOM element if rule conditions met
@@ -5840,17 +5841,25 @@
58405841
});
58415842

58425843
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5843-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5844+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
58445845
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5846+
// query original node instead of parsedNode for img elements since heuristic relies
5847+
// on size of image elements
5848+
const imageElements = [...node.querySelectorAll('img,svg')];
58455849
// about:blank iframes don't count as content, return true if:
58465850
// - node doesn't contain any iframes
58475851
// - node contains iframes, all of which are hidden or have src='about:blank'
58485852
const noFramesWithContent = frameElements.every((frame) => {
58495853
return (frame.hidden || frame.src === 'about:blank')
58505854
});
5855+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5856+
// these should be treated as empty and hidden, but real images should not.
5857+
const visibleImages = imageElements.some((image) => {
5858+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5859+
});
58515860

58525861
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5853-
noFramesWithContent && mediaContent === null) {
5862+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
58545863
return true
58555864
}
58565865
return false
@@ -5990,6 +5999,7 @@
59905999
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
59916000
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
59926001
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6002+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
59936003

59946004
// determine whether strict hide rules should be injected as a style tag
59956005
if (shouldInjectStyleTag) {

build/windows/contentScope.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5801,6 +5801,7 @@
58015801
let hiddenElements = new WeakMap();
58025802
let appliedRules = new Set();
58035803
let shouldInjectStyleTag = false;
5804+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';
58045805

58055806
/**
58065807
* Hide DOM element if rule conditions met
@@ -5929,17 +5930,25 @@
59295930
});
59305931

59315932
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '');
5932-
const mediaContent = parsedNode.querySelector('video,canvas,picture');
5933+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors);
59335934
const frameElements = [...parsedNode.querySelectorAll('iframe')];
5935+
// query original node instead of parsedNode for img elements since heuristic relies
5936+
// on size of image elements
5937+
const imageElements = [...node.querySelectorAll('img,svg')];
59345938
// about:blank iframes don't count as content, return true if:
59355939
// - node doesn't contain any iframes
59365940
// - node contains iframes, all of which are hidden or have src='about:blank'
59375941
const noFramesWithContent = frameElements.every((frame) => {
59385942
return (frame.hidden || frame.src === 'about:blank')
59395943
});
5944+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
5945+
// these should be treated as empty and hidden, but real images should not.
5946+
const visibleImages = imageElements.some((image) => {
5947+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
5948+
});
59405949

59415950
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
5942-
noFramesWithContent && mediaContent === null) {
5951+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
59435952
return true
59445953
}
59455954
return false
@@ -6079,6 +6088,7 @@
60796088
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions');
60806089
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings');
60816090
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag');
6091+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors;
60826092

60836093
// determine whether strict hide rules should be injected as a style tag
60846094
if (shouldInjectStyleTag) {

src/features/element-hiding.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const parser = new DOMParser()
55
let hiddenElements = new WeakMap()
66
let appliedRules = new Set()
77
let shouldInjectStyleTag = false
8+
let mediaAndFormSelectors = 'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button'
89

910
/**
1011
* Hide DOM element if rule conditions met
@@ -137,17 +138,25 @@ function isDomNodeEmpty (node) {
137138
})
138139

139140
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '')
140-
const mediaContent = parsedNode.querySelector('video,canvas,picture')
141+
const mediaAndFormContent = parsedNode.querySelector(mediaAndFormSelectors)
141142
const frameElements = [...parsedNode.querySelectorAll('iframe')]
143+
// query original node instead of parsedNode for img elements since heuristic relies
144+
// on size of image elements
145+
const imageElements = [...node.querySelectorAll('img,svg')]
142146
// about:blank iframes don't count as content, return true if:
143147
// - node doesn't contain any iframes
144148
// - node contains iframes, all of which are hidden or have src='about:blank'
145149
const noFramesWithContent = frameElements.every((frame) => {
146150
return (frame.hidden || frame.src === 'about:blank')
147151
})
152+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
153+
// these should be treated as empty and hidden, but real images should not.
154+
const visibleImages = imageElements.some((image) => {
155+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
156+
})
148157

149158
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
150-
noFramesWithContent && mediaContent === null) {
159+
mediaAndFormContent === null && noFramesWithContent && !visibleImages) {
151160
return true
152161
}
153162
return false
@@ -287,6 +296,7 @@ export function init (args) {
287296
const styleTagExceptions = getFeatureSetting(featureName, args, 'styleTagExceptions')
288297
adLabelStrings = getFeatureSetting(featureName, args, 'adLabelStrings')
289298
shouldInjectStyleTag = getFeatureSetting(featureName, args, 'useStrictHideStyleTag')
299+
mediaAndFormSelectors = getFeatureSetting(featureName, args, 'mediaAndFormSelectors') || mediaAndFormSelectors
290300

291301
// determine whether strict hide rules should be injected as a style tag
292302
if (shouldInjectStyleTag) {

unit-test/dirSize.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import fastFolderSizeSync from 'fast-folder-size/sync.js'
44
const buildDirs = ['android', 'chrome', 'chrome-mv3', 'firefox', 'integration', 'windows']
55
// Lets sanity check build sizes, picking 512KB as a rather arbitrary limit
66
// Higher for Chrome MV2 due to base64 encoding
7-
const quotas = [512000, 680960, 512000, 512000, 512000, 512000]
7+
const quotas = [512000, 716800, 512000, 512000, 512000, 512000]
88
const rootDir = 'build'
99

1010
describe('Expect build size of', () => {

0 commit comments

Comments
 (0)