1
- import { NUMBER_OF_ITEMS } from "./constants"
1
+ import { NUMBER_OF_LITERALS } from "./constants"
2
+ import Optimizer from "./optimizer"
2
3
3
4
const blurFilter = "blur(0.343em)" // This unique filter value identifies the OpenBlur filter.
4
5
const tagsNotToBlur = [ "HEAD" , "SCRIPT" , "STYLE" , "loc" ]
@@ -8,6 +9,12 @@ let enabled = true
8
9
let bodyHidden = true
9
10
let doFullScan = false
10
11
12
+ // Performance optimization. The performance optimization mode is enabled when we blur a lot of elements in a short period of time.
13
+ const maxBlursCount = 100
14
+ let blursCount = maxBlursCount
15
+ const performanceOptimizationResetMs = 5 * 1000
16
+ let performanceOptimizationMode = false
17
+
11
18
console . debug ( "OpenBlur content script loaded" )
12
19
13
20
function unhideBody ( ) {
@@ -18,28 +25,36 @@ function unhideBody() {
18
25
}
19
26
20
27
function processInputElement ( input : HTMLInputElement | HTMLTextAreaElement ) {
28
+ let blurTarget : HTMLElement = input
29
+ if ( performanceOptimizationMode && input . parentElement instanceof HTMLElement ) {
30
+ // In performance optimization mode, we may blur the parent.
31
+ const grandParent = input . parentElement as HTMLElement
32
+ if ( grandParent . style && grandParent . style . filter . includes ( blurFilter ) ) {
33
+ // Treat the grandparent as the parent.
34
+ blurTarget = grandParent
35
+ }
36
+ }
21
37
let text = input . value || input . getAttribute ( "value" ) || ""
22
- if ( input . style . filter . includes ( blurFilter ) ) {
38
+ if ( blurTarget . style . filter . includes ( blurFilter ) ) {
23
39
// Already blurred
24
40
if ( ! enabled ) {
25
41
// We remove the blur filter if the extension is disabled.
26
- input . style . filter = input . style . filter . replace ( blurFilter , "" )
42
+ unblurElement ( blurTarget )
27
43
return
28
44
}
29
45
const blurNeeded = contentToBlur . some ( ( content ) => {
30
46
return text . includes ( content ) ;
31
47
} )
32
48
if ( ! blurNeeded ) {
33
- input . style . filter = input . style . filter . replace ( blurFilter , "" )
49
+ unblurElement ( blurTarget )
34
50
}
35
51
return
36
- }
37
- if ( enabled && text . length > 0 ) {
52
+ } else if ( enabled && text . length > 0 ) {
38
53
const blurNeeded = contentToBlur . some ( ( content ) => {
39
54
return text . includes ( content ) ;
40
55
} )
41
56
if ( blurNeeded ) {
42
- blurElement ( input )
57
+ blurElement ( blurTarget )
43
58
}
44
59
}
45
60
}
@@ -52,14 +67,22 @@ function processNode(node: Node) {
52
67
Array . from ( node . childNodes ) . forEach ( processNode )
53
68
}
54
69
if ( node . nodeType === Node . TEXT_NODE && node . textContent !== null && node . textContent . trim ( ) . length > 0 ) {
55
- const parent = node . parentElement
70
+ let parent = node . parentElement
56
71
if ( parent !== null && parent . style ) {
57
72
const text = node . textContent !
73
+ if ( performanceOptimizationMode && parent . parentElement instanceof HTMLElement ) {
74
+ // In performance optimization mode, we may blur the parent's parent.
75
+ const grandParent = parent . parentElement as HTMLElement
76
+ if ( grandParent . style && grandParent . style . filter . includes ( blurFilter ) ) {
77
+ // Treat the grandparent as the parent.
78
+ parent = grandParent
79
+ }
80
+ }
58
81
if ( parent . style . filter . includes ( blurFilter ) ) {
59
82
// Already blurred
60
83
if ( ! enabled ) {
61
84
// We remove the blur filter if the extension is disabled.
62
- parent . style . filter = parent . style . filter . replace ( blurFilter , "" )
85
+ unblurElement ( parent )
63
86
return
64
87
}
65
88
if ( doFullScan ) {
@@ -68,12 +91,11 @@ function processNode(node: Node) {
68
91
return text . includes ( content ) ;
69
92
} )
70
93
if ( ! blurNeeded ) {
71
- parent . style . filter = parent . style . filter . replace ( blurFilter , "" )
94
+ unblurElement ( parent )
72
95
}
73
96
}
74
97
return
75
- }
76
- if ( enabled ) {
98
+ } else if ( enabled ) {
77
99
const blurNeeded = contentToBlur . some ( ( content ) => {
78
100
return text . includes ( content ) ;
79
101
} )
@@ -99,14 +121,37 @@ function processNode(node: Node) {
99
121
}
100
122
101
123
function blurElement ( elem : HTMLElement ) {
102
- if ( elem . style . filter . length == 0 ) {
103
- elem . style . filter = blurFilter
124
+ let blurTarget : HTMLElement = elem
125
+ if ( performanceOptimizationMode ) {
126
+ const ok = Optimizer . addElement ( elem )
127
+ if ( ! ok ) {
128
+ blurTarget = elem . parentElement as HTMLElement
129
+ void Optimizer . addElement ( elem )
130
+ }
131
+ }
132
+ if ( blurTarget . style . filter . length == 0 ) {
133
+ blurTarget . style . filter = blurFilter
104
134
} else {
105
135
// The element already has a filter. Append our blur filter to the existing filter.
106
136
// We assume that the semicolon(;) is never present in the filter string. This has been the case in our limited testing.
107
- elem . style . filter += ` ${ blurFilter } `
137
+ blurTarget . style . filter += ` ${ blurFilter } `
108
138
}
109
139
console . debug ( "OpenBlur blurred element id:%s, class:%s, tag:%s, text:%s" , elem . id , elem . className , elem . tagName , elem . textContent )
140
+ blursCount --
141
+ if ( blursCount <= 0 ) {
142
+ if ( ! performanceOptimizationMode ) {
143
+ console . debug ( "OpenBlur performance optimization mode enabled" )
144
+ performanceOptimizationMode = true
145
+ }
146
+ }
147
+ }
148
+
149
+ function unblurElement ( elem : HTMLElement ) {
150
+ elem . style . filter = elem . style . filter . replace ( blurFilter , "" )
151
+ if ( performanceOptimizationMode ) {
152
+ Optimizer . removeElement ( elem )
153
+ }
154
+ console . debug ( "OpenBlur unblurred element id:%s, class:%s, tag:%s, text:%s" , elem . id , elem . className , elem . tagName , elem . textContent )
110
155
}
111
156
112
157
const observer = new MutationObserver ( ( mutations ) => {
@@ -147,11 +192,15 @@ function disconnectInputs() {
147
192
function disconnect ( ) {
148
193
observer . disconnect ( )
149
194
disconnectInputs ( )
195
+ if ( performanceOptimizationMode ) {
196
+ Optimizer . clear ( )
197
+ performanceOptimizationMode = false
198
+ }
150
199
}
151
200
152
201
function setLiterals ( literals : string [ ] ) {
153
202
contentToBlur . length = 0
154
- for ( let i = 0 ; i < NUMBER_OF_ITEMS ; i ++ ) {
203
+ for ( let i = 0 ; i < NUMBER_OF_LITERALS ; i ++ ) {
155
204
const item : string = literals [ i ]
156
205
if ( item && item . trim ( ) . length > 0 ) {
157
206
contentToBlur . push ( item . trim ( ) )
@@ -191,3 +240,7 @@ chrome.runtime.onMessage.addListener((request, _sender, _sendResponse) => {
191
240
setLiterals ( request . literals )
192
241
}
193
242
} )
243
+
244
+ setInterval ( ( ) => {
245
+ blursCount = maxBlursCount
246
+ } , performanceOptimizationResetMs )
0 commit comments