@ginger-ai/ginger-js 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +88 -0
  2. package/dist/ginger.cjs.js +2 -0
  3. package/dist/ginger.cjs.js.map +1 -0
  4. package/dist/ginger.esm.d.ts +294 -0
  5. package/dist/ginger.esm.js +2 -0
  6. package/dist/ginger.esm.js.map +1 -0
  7. package/dist/ginger.umd.js +2 -0
  8. package/dist/ginger.umd.js.map +1 -0
  9. package/dist/types/behaviour/index.d.ts +49 -0
  10. package/dist/types/behaviour/index.d.ts.map +1 -0
  11. package/dist/types/client/index.d.ts +35 -0
  12. package/dist/types/client/index.d.ts.map +1 -0
  13. package/dist/types/core/constants.d.ts +5 -0
  14. package/dist/types/core/constants.d.ts.map +1 -0
  15. package/dist/types/core/dto/bot-detector.dto.d.ts +30 -0
  16. package/dist/types/core/dto/bot-detector.dto.d.ts.map +1 -0
  17. package/dist/types/core/dto/device-detector.dto.d.ts +54 -0
  18. package/dist/types/core/dto/device-detector.dto.d.ts.map +1 -0
  19. package/dist/types/core/dto/fingerprint.dto.d.ts +29 -0
  20. package/dist/types/core/dto/fingerprint.dto.d.ts.map +1 -0
  21. package/dist/types/core/dto/ginger.dto.d.ts +73 -0
  22. package/dist/types/core/dto/ginger.dto.d.ts.map +1 -0
  23. package/dist/types/core/dto/incognito-detector.dto.d.ts +4 -0
  24. package/dist/types/core/dto/incognito-detector.dto.d.ts.map +1 -0
  25. package/dist/types/core/dto/index.d.ts +10 -0
  26. package/dist/types/core/dto/index.d.ts.map +1 -0
  27. package/dist/types/core/dto/metrics.dto.d.ts +19 -0
  28. package/dist/types/core/dto/metrics.dto.d.ts.map +1 -0
  29. package/dist/types/core/dto/os-detector.dto.d.ts +6 -0
  30. package/dist/types/core/dto/os-detector.dto.d.ts.map +1 -0
  31. package/dist/types/core/dto/tor-detector.dto.d.ts +5 -0
  32. package/dist/types/core/dto/tor-detector.dto.d.ts.map +1 -0
  33. package/dist/types/core/helpers.d.ts +8 -0
  34. package/dist/types/core/helpers.d.ts.map +1 -0
  35. package/dist/types/core/http/httpClient.d.ts +28 -0
  36. package/dist/types/core/http/httpClient.d.ts.map +1 -0
  37. package/dist/types/core/http/request.d.ts +4 -0
  38. package/dist/types/core/http/request.d.ts.map +1 -0
  39. package/dist/types/core/index.d.ts +6 -0
  40. package/dist/types/core/index.d.ts.map +1 -0
  41. package/dist/types/core/util/error.d.ts +25 -0
  42. package/dist/types/core/util/error.d.ts.map +1 -0
  43. package/dist/types/core/util/generate-requestid.d.ts +2 -0
  44. package/dist/types/core/util/generate-requestid.d.ts.map +1 -0
  45. package/dist/types/device/components/audio/audio.d.ts +2 -0
  46. package/dist/types/device/components/audio/audio.d.ts.map +1 -0
  47. package/dist/types/device/components/canvas/canvas.d.ts +3 -0
  48. package/dist/types/device/components/canvas/canvas.d.ts.map +1 -0
  49. package/dist/types/device/components/extra/extra.d.ts +19 -0
  50. package/dist/types/device/components/extra/extra.d.ts.map +1 -0
  51. package/dist/types/device/components/fonts/fonts.d.ts +3 -0
  52. package/dist/types/device/components/fonts/fonts.d.ts.map +1 -0
  53. package/dist/types/device/components/hardware/hardware.d.ts +2 -0
  54. package/dist/types/device/components/hardware/hardware.d.ts.map +1 -0
  55. package/dist/types/device/components/index.d.ts +15 -0
  56. package/dist/types/device/components/index.d.ts.map +1 -0
  57. package/dist/types/device/components/locales/locales.d.ts +2 -0
  58. package/dist/types/device/components/locales/locales.d.ts.map +1 -0
  59. package/dist/types/device/components/math/math.d.ts +2 -0
  60. package/dist/types/device/components/math/math.d.ts.map +1 -0
  61. package/dist/types/device/components/permissions/permissions.d.ts +3 -0
  62. package/dist/types/device/components/permissions/permissions.d.ts.map +1 -0
  63. package/dist/types/device/components/plugins/plugins.d.ts +3 -0
  64. package/dist/types/device/components/plugins/plugins.d.ts.map +1 -0
  65. package/dist/types/device/components/screen/screen.d.ts +2 -0
  66. package/dist/types/device/components/screen/screen.d.ts.map +1 -0
  67. package/dist/types/device/components/screen/screenResolution.d.ts +16 -0
  68. package/dist/types/device/components/screen/screenResolution.d.ts.map +1 -0
  69. package/dist/types/device/components/system/browser.d.ts +22 -0
  70. package/dist/types/device/components/system/browser.d.ts.map +1 -0
  71. package/dist/types/device/components/system/emoji.d.ts +2 -0
  72. package/dist/types/device/components/system/emoji.d.ts.map +1 -0
  73. package/dist/types/device/components/system/system.d.ts +2 -0
  74. package/dist/types/device/components/system/system.d.ts.map +1 -0
  75. package/dist/types/device/components/webgl/imageHash.d.ts +3 -0
  76. package/dist/types/device/components/webgl/imageHash.d.ts.map +1 -0
  77. package/dist/types/device/components/webgl/webgl.d.ts +54 -0
  78. package/dist/types/device/components/webgl/webgl.d.ts.map +1 -0
  79. package/dist/types/device/factory.d.ts +26 -0
  80. package/dist/types/device/factory.d.ts.map +1 -0
  81. package/dist/types/device/index.d.ts +61 -0
  82. package/dist/types/device/index.d.ts.map +1 -0
  83. package/dist/types/device/modules/bot.d.ts +9 -0
  84. package/dist/types/device/modules/bot.d.ts.map +1 -0
  85. package/dist/types/device/modules/browserDetails.d.ts +6 -0
  86. package/dist/types/device/modules/browserDetails.d.ts.map +1 -0
  87. package/dist/types/device/modules/device/analyze-data.d.ts +7 -0
  88. package/dist/types/device/modules/device/analyze-data.d.ts.map +1 -0
  89. package/dist/types/device/modules/device/gather-data.d.ts +6 -0
  90. package/dist/types/device/modules/device/gather-data.d.ts.map +1 -0
  91. package/dist/types/device/modules/device/helpers.d.ts +9 -0
  92. package/dist/types/device/modules/device/helpers.d.ts.map +1 -0
  93. package/dist/types/device/modules/device/index.d.ts +3 -0
  94. package/dist/types/device/modules/device/index.d.ts.map +1 -0
  95. package/dist/types/device/modules/fp.d.ts +14 -0
  96. package/dist/types/device/modules/fp.d.ts.map +1 -0
  97. package/dist/types/device/modules/incognito.d.ts +7 -0
  98. package/dist/types/device/modules/incognito.d.ts.map +1 -0
  99. package/dist/types/device/modules/options.d.ts +12 -0
  100. package/dist/types/device/modules/options.d.ts.map +1 -0
  101. package/dist/types/device/modules/os.d.ts +3 -0
  102. package/dist/types/device/modules/os.d.ts.map +1 -0
  103. package/dist/types/device/modules/tor.d.ts +4 -0
  104. package/dist/types/device/modules/tor.d.ts.map +1 -0
  105. package/dist/types/device/utils/async.d.ts +33 -0
  106. package/dist/types/device/utils/async.d.ts.map +1 -0
  107. package/dist/types/device/utils/browser_.d.ts +103 -0
  108. package/dist/types/device/utils/browser_.d.ts.map +1 -0
  109. package/dist/types/device/utils/commonPixels.d.ts +2 -0
  110. package/dist/types/device/utils/commonPixels.d.ts.map +1 -0
  111. package/dist/types/device/utils/data.d.ts +33 -0
  112. package/dist/types/device/utils/data.d.ts.map +1 -0
  113. package/dist/types/device/utils/dom.d.ts +26 -0
  114. package/dist/types/device/utils/dom.d.ts.map +1 -0
  115. package/dist/types/device/utils/ephemeralIFrame.d.ts +5 -0
  116. package/dist/types/device/utils/ephemeralIFrame.d.ts.map +1 -0
  117. package/dist/types/device/utils/getMostFrequent.d.ts +6 -0
  118. package/dist/types/device/utils/getMostFrequent.d.ts.map +1 -0
  119. package/dist/types/device/utils/hash.d.ts +6 -0
  120. package/dist/types/device/utils/hash.d.ts.map +1 -0
  121. package/dist/types/device/utils/misc.d.ts +7 -0
  122. package/dist/types/device/utils/misc.d.ts.map +1 -0
  123. package/dist/types/device/utils/raceAll.d.ts +9 -0
  124. package/dist/types/device/utils/raceAll.d.ts.map +1 -0
  125. package/dist/types/index.d.ts +4 -0
  126. package/dist/types/index.d.ts.map +1 -0
  127. package/package.json +52 -0
  128. package/src/behaviour/index.ts +279 -0
  129. package/src/client/index.ts +132 -0
  130. package/src/core/constants.ts +4 -0
  131. package/src/core/dto/bot-detector.dto.ts +32 -0
  132. package/src/core/dto/device-detector.dto.ts +67 -0
  133. package/src/core/dto/fingerprint.dto.ts +38 -0
  134. package/src/core/dto/ginger.dto.ts +89 -0
  135. package/src/core/dto/incognito-detector.dto.ts +2 -0
  136. package/src/core/dto/index.ts +18 -0
  137. package/src/core/dto/metrics.dto.ts +20 -0
  138. package/src/core/dto/os-detector.dto.ts +5 -0
  139. package/src/core/dto/tor-detector.dto.ts +4 -0
  140. package/src/core/helpers.ts +33 -0
  141. package/src/core/http/httpClient.ts +52 -0
  142. package/src/core/http/request.ts +32 -0
  143. package/src/core/index.ts +5 -0
  144. package/src/core/util/error.ts +40 -0
  145. package/src/core/util/generate-requestid.ts +63 -0
  146. package/src/device/components/audio/audio.ts +58 -0
  147. package/src/device/components/canvas/canvas.ts +88 -0
  148. package/src/device/components/extra/extra.ts +581 -0
  149. package/src/device/components/fonts/fonts.ts +143 -0
  150. package/src/device/components/hardware/hardware.ts +66 -0
  151. package/src/device/components/index.ts +14 -0
  152. package/src/device/components/locales/locales.ts +21 -0
  153. package/src/device/components/math/math.ts +39 -0
  154. package/src/device/components/permissions/permissions.ts +60 -0
  155. package/src/device/components/plugins/plugins.ts +22 -0
  156. package/src/device/components/screen/screen.ts +13 -0
  157. package/src/device/components/screen/screenResolution.ts +45 -0
  158. package/src/device/components/system/browser.ts +838 -0
  159. package/src/device/components/system/emoji.ts +134 -0
  160. package/src/device/components/system/system.ts +76 -0
  161. package/src/device/components/webgl/imageHash.ts +144 -0
  162. package/src/device/components/webgl/webgl.ts +302 -0
  163. package/src/device/factory.ts +54 -0
  164. package/src/device/index.ts +60 -0
  165. package/src/device/modules/bot.ts +25 -0
  166. package/src/device/modules/browserDetails.ts +11 -0
  167. package/src/device/modules/device/analyze-data.ts +150 -0
  168. package/src/device/modules/device/gather-data.ts +92 -0
  169. package/src/device/modules/device/helpers.ts +123 -0
  170. package/src/device/modules/device/index.ts +64 -0
  171. package/src/device/modules/fp.ts +138 -0
  172. package/src/device/modules/incognito.ts +253 -0
  173. package/src/device/modules/options.ts +17 -0
  174. package/src/device/modules/os.ts +15 -0
  175. package/src/device/modules/tor.ts +41 -0
  176. package/src/device/utils/async.ts +106 -0
  177. package/src/device/utils/browser_.ts +347 -0
  178. package/src/device/utils/commonPixels.ts +38 -0
  179. package/src/device/utils/data.ts +161 -0
  180. package/src/device/utils/dom.ts +148 -0
  181. package/src/device/utils/ephemeralIFrame.ts +35 -0
  182. package/src/device/utils/getMostFrequent.ts +39 -0
  183. package/src/device/utils/hash.ts +202 -0
  184. package/src/device/utils/misc.ts +18 -0
  185. package/src/device/utils/raceAll.ts +19 -0
  186. package/src/index.ts +3 -0
@@ -0,0 +1,581 @@
1
+ import { includeComponent } from "../../factory";
2
+
3
+ import { selectorToElement } from "../../utils/dom";
4
+ import { countTruthy } from "../../utils/data";
5
+ import { wait } from "../../utils/async";
6
+ import { isAndroid, isWebKit } from "../../utils/browser_";
7
+ import { detectBrowser } from "../system/browser";
8
+
9
+ // Floating-point calculations (Math.sin(), Math.log()) produce slightly different results across CPUs due to:
10
+ // Extremely hard to spoof without emulating a different CPU.
11
+ // function getCPUFingerprint(): any {
12
+ // return {
13
+ // sin1: Math.sin(1),
14
+ // log10: Math.log(10),
15
+ // tanh05: Math.tanh(0.5),
16
+ // };
17
+ // }
18
+
19
+ const enum SpecialFingerprint {
20
+ /** The browser doesn't support AudioContext or baseLatency */
21
+ NotSupported = -1,
22
+ /** Entropy source is disabled because of console warnings */
23
+ Disabled = -2,
24
+ }
25
+
26
+ function getAudioContextBaseLatency(): any {
27
+ // The signal emits warning in Chrome and Firefox, therefore it is enabled on Safari where it doesn't produce warning
28
+ // and on Android where it's less visible
29
+ const isAllowedPlatform = isAndroid() || isWebKit();
30
+ if (!isAllowedPlatform) {
31
+ return SpecialFingerprint.Disabled;
32
+ }
33
+
34
+ if (!window.AudioContext) {
35
+ return SpecialFingerprint.NotSupported;
36
+ }
37
+ return new AudioContext().baseLatency ?? SpecialFingerprint.NotSupported;
38
+ }
39
+
40
+ /**
41
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut
42
+ */
43
+ function getColorGamut(): any {
44
+ // rec2020 includes p3 and p3 includes srgb
45
+ for (const gamut of ["rec2020", "p3", "srgb"] as const) {
46
+ if (matchMedia(`(color-gamut: ${gamut})`).matches) {
47
+ return gamut;
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+
53
+ function areColorsForced(): any {
54
+ if (doesMatch("active")) {
55
+ return true;
56
+ }
57
+ if (doesMatch("none")) {
58
+ return false;
59
+ }
60
+ return undefined;
61
+ }
62
+
63
+ function doesMatch(value: string) {
64
+ return matchMedia(`(forced-colors: ${value})`).matches;
65
+ }
66
+
67
+ const maxValueToCheck = 100;
68
+
69
+ /**
70
+ * If the display is monochrome (e.g. black&white), the value will be ≥0 and will mean the number of bits per pixel.
71
+ * If the display is not monochrome, the returned value will be 0.
72
+ * If the browser doesn't support this feature, the returned value will be undefined.
73
+ *
74
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/monochrome
75
+ */
76
+ function getMonochromeDepth(): any {
77
+ if (!matchMedia("(min-monochrome: 0)").matches) {
78
+ // The media feature isn't supported by the browser
79
+ return undefined;
80
+ }
81
+
82
+ // A variation of binary search algorithm can be used here.
83
+ // But since expected values are very small (≤10), there is no sense in adding the complexity.
84
+ for (let i = 0; i <= maxValueToCheck; ++i) {
85
+ if (matchMedia(`(max-monochrome: ${i})`).matches) {
86
+ return i;
87
+ }
88
+ }
89
+
90
+ throw new Error("Too high value");
91
+ }
92
+
93
+ function getOsCpu(): any {
94
+ return (navigator as any).oscpu;
95
+ }
96
+
97
+ /**
98
+ * Checks for browser-specific (not engine specific) global variables to tell browsers with the same engine apart.
99
+ * Only somewhat popular browsers are considered.
100
+ */
101
+ export function getVendorFlavors(): any {
102
+ const flavors: string[] = [];
103
+
104
+ for (const key of [
105
+ // Blink and some browsers on iOS
106
+ "chrome",
107
+
108
+ // Safari on macOS
109
+ "safari",
110
+
111
+ // Chrome on iOS (checked in 85 on 13 and 87 on 14)
112
+ "__crWeb",
113
+ "__gCrWeb",
114
+
115
+ // Yandex Browser on iOS, macOS and Android (checked in 21.2 on iOS 14, macOS and Android)
116
+ "yandex",
117
+
118
+ // Yandex Browser on iOS (checked in 21.2 on 14)
119
+ "__yb",
120
+ "__ybro",
121
+
122
+ // Firefox on iOS (checked in 32 on 14)
123
+ "__firefox__",
124
+
125
+ // Edge on iOS (checked in 46 on 14)
126
+ "__edgeTrackingPreventionStatistics",
127
+ "webkit",
128
+
129
+ // Opera Touch on iOS (checked in 2.6 on 14)
130
+ "oprt",
131
+
132
+ // Samsung Internet on Android (checked in 11.1)
133
+ "samsungAr",
134
+
135
+ // UC Browser on Android (checked in 12.10 and 13.0)
136
+ "ucweb",
137
+ "UCShellJava",
138
+
139
+ // Puffin on Android (checked in 9.0)
140
+ "puffinDevice",
141
+
142
+ // UC on iOS and Opera on Android have no specific global variables
143
+ // Edge for Android isn't checked
144
+ ]) {
145
+ const value = (window as unknown as Record<string, unknown>)[key];
146
+ if (value && typeof value === "object") {
147
+ flavors.push(key);
148
+ }
149
+ }
150
+
151
+ const sortedVendorFlavors = flavors.sort();
152
+
153
+ // If no vendor flavor is detected, default to use the browser name
154
+ if (sortedVendorFlavors.length > 0) {
155
+ return sortedVendorFlavors;
156
+ } else {
157
+ const { name: browsername } = detectBrowser();
158
+ return [browsername];
159
+ }
160
+ }
161
+
162
+ type Filters = Record<string, string[]>;
163
+
164
+ /**
165
+ * Only single element selector are supported (no operators like space, +, >, etc).
166
+ * `embed` and `position: fixed;` will be considered as blocked anyway because it always has no offsetParent.
167
+ * Avoid `iframe` and anything with `[src=]` because they produce excess HTTP requests.
168
+ *
169
+ * The "inappropriate" selectors are obfuscated. See https://github.com/fingerprintjs/fingerprintjs/issues/734.
170
+ * A function is used instead of a plain object to help tree-shaking.
171
+ *
172
+ * The function code is generated automatically. See docs/content_blockers.md to learn how to make the list.
173
+ */
174
+ export function getFilters(): Filters {
175
+ const fromB64 = atob; // Just for better minification
176
+
177
+ return {
178
+ abpIndo: [
179
+ "#Iklan-Melayang",
180
+ "#Kolom-Iklan-728",
181
+ "#SidebarIklan-wrapper",
182
+ '[title="ALIENBOLA" i]',
183
+ fromB64("I0JveC1CYW5uZXItYWRz"),
184
+ ],
185
+ abpvn: [
186
+ ".quangcao",
187
+ "#mobileCatfish",
188
+ fromB64("LmNsb3NlLWFkcw=="),
189
+ '[id^="bn_bottom_fixed_"]',
190
+ "#pmadv",
191
+ ],
192
+ adBlockFinland: [
193
+ ".mainostila",
194
+ fromB64("LnNwb25zb3JpdA=="),
195
+ ".ylamainos",
196
+ fromB64("YVtocmVmKj0iL2NsaWNrdGhyZ2guYXNwPyJd"),
197
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9hcHAucmVhZHBlYWsuY29tL2FkcyJd"),
198
+ ],
199
+ adBlockPersian: [
200
+ "#navbar_notice_50",
201
+ ".kadr",
202
+ 'TABLE[width="140px"]',
203
+ "#divAgahi",
204
+ fromB64("YVtocmVmXj0iaHR0cDovL2cxLnYuZndtcm0ubmV0L2FkLyJd"),
205
+ ],
206
+ adBlockWarningRemoval: [
207
+ "#adblock-honeypot",
208
+ ".adblocker-root",
209
+ ".wp_adblock_detect",
210
+ fromB64("LmhlYWRlci1ibG9ja2VkLWFk"),
211
+ fromB64("I2FkX2Jsb2NrZXI="),
212
+ ],
213
+ adGuardAnnoyances: [
214
+ ".hs-sosyal",
215
+ "#cookieconsentdiv",
216
+ 'div[class^="app_gdpr"]',
217
+ ".as-oil",
218
+ '[data-cypress="soft-push-notification-modal"]',
219
+ ],
220
+ adGuardBase: [
221
+ ".BetterJsPopOverlay",
222
+ fromB64("I2FkXzMwMFgyNTA="),
223
+ fromB64("I2Jhbm5lcmZsb2F0MjI="),
224
+ fromB64("I2NhbXBhaWduLWJhbm5lcg=="),
225
+ fromB64("I0FkLUNvbnRlbnQ="),
226
+ ],
227
+ adGuardChinese: [
228
+ fromB64("LlppX2FkX2FfSA=="),
229
+ fromB64("YVtocmVmKj0iLmh0aGJldDM0LmNvbSJd"),
230
+ "#widget-quan",
231
+ fromB64("YVtocmVmKj0iLzg0OTkyMDIwLnh5eiJd"),
232
+ fromB64("YVtocmVmKj0iLjE5NTZobC5jb20vIl0="),
233
+ ],
234
+ adGuardFrench: [
235
+ "#pavePub",
236
+ fromB64("LmFkLWRlc2t0b3AtcmVjdGFuZ2xl"),
237
+ ".mobile_adhesion",
238
+ ".widgetadv",
239
+ fromB64("LmFkc19iYW4="),
240
+ ],
241
+ adGuardGerman: ['aside[data-portal-id="leaderboard"]'],
242
+ adGuardJapanese: [
243
+ "#kauli_yad_1",
244
+ fromB64("YVtocmVmXj0iaHR0cDovL2FkMi50cmFmZmljZ2F0ZS5uZXQvIl0="),
245
+ fromB64("Ll9wb3BJbl9pbmZpbml0ZV9hZA=="),
246
+ fromB64("LmFkZ29vZ2xl"),
247
+ fromB64("Ll9faXNib29zdFJldHVybkFk"),
248
+ ],
249
+ adGuardMobile: [
250
+ fromB64("YW1wLWF1dG8tYWRz"),
251
+ fromB64("LmFtcF9hZA=="),
252
+ 'amp-embed[type="24smi"]',
253
+ "#mgid_iframe1",
254
+ fromB64("I2FkX2ludmlld19hcmVh"),
255
+ ],
256
+ adGuardRussian: [
257
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZC5sZXRtZWFkcy5jb20vIl0="),
258
+ fromB64("LnJlY2xhbWE="),
259
+ 'div[id^="smi2adblock"]',
260
+ fromB64("ZGl2W2lkXj0iQWRGb3hfYmFubmVyXyJd"),
261
+ "#psyduckpockeball",
262
+ ],
263
+ adGuardSocial: [
264
+ fromB64("YVtocmVmXj0iLy93d3cuc3R1bWJsZXVwb24uY29tL3N1Ym1pdD91cmw9Il0="),
265
+ fromB64("YVtocmVmXj0iLy90ZWxlZ3JhbS5tZS9zaGFyZS91cmw/Il0="),
266
+ ".etsy-tweet",
267
+ "#inlineShare",
268
+ ".popup-social",
269
+ ],
270
+ adGuardSpanishPortuguese: [
271
+ "#barraPublicidade",
272
+ "#Publicidade",
273
+ "#publiEspecial",
274
+ "#queTooltip",
275
+ ".cnt-publi",
276
+ ],
277
+ adGuardTrackingProtection: [
278
+ "#qoo-counter",
279
+ fromB64("YVtocmVmXj0iaHR0cDovL2NsaWNrLmhvdGxvZy5ydS8iXQ=="),
280
+ fromB64("YVtocmVmXj0iaHR0cDovL2hpdGNvdW50ZXIucnUvdG9wL3N0YXQucGhwIl0="),
281
+ fromB64("YVtocmVmXj0iaHR0cDovL3RvcC5tYWlsLnJ1L2p1bXAiXQ=="),
282
+ "#top100counter",
283
+ ],
284
+ adGuardTurkish: [
285
+ "#backkapat",
286
+ fromB64("I3Jla2xhbWk="),
287
+ fromB64("YVtocmVmXj0iaHR0cDovL2Fkc2Vydi5vbnRlay5jb20udHIvIl0="),
288
+ fromB64("YVtocmVmXj0iaHR0cDovL2l6bGVuemkuY29tL2NhbXBhaWduLyJd"),
289
+ fromB64("YVtocmVmXj0iaHR0cDovL3d3dy5pbnN0YWxsYWRzLm5ldC8iXQ=="),
290
+ ],
291
+ bulgarian: [
292
+ fromB64("dGQjZnJlZW5ldF90YWJsZV9hZHM="),
293
+ "#ea_intext_div",
294
+ ".lapni-pop-over",
295
+ "#xenium_hot_offers",
296
+ ],
297
+ easyList: [
298
+ ".yb-floorad",
299
+ fromB64("LndpZGdldF9wb19hZHNfd2lkZ2V0"),
300
+ fromB64("LnRyYWZmaWNqdW5reS1hZA=="),
301
+ ".textad_headline",
302
+ fromB64("LnNwb25zb3JlZC10ZXh0LWxpbmtz"),
303
+ ],
304
+ easyListChina: [
305
+ fromB64("LmFwcGd1aWRlLXdyYXBbb25jbGljayo9ImJjZWJvcy5jb20iXQ=="),
306
+ fromB64("LmZyb250cGFnZUFkdk0="),
307
+ "#taotaole",
308
+ "#aafoot.top_box",
309
+ ".cfa_popup",
310
+ ],
311
+ easyListCookie: [
312
+ ".ezmob-footer",
313
+ ".cc-CookieWarning",
314
+ "[data-cookie-number]",
315
+ fromB64("LmF3LWNvb2tpZS1iYW5uZXI="),
316
+ ".sygnal24-gdpr-modal-wrap",
317
+ ],
318
+ easyListCzechSlovak: [
319
+ "#onlajny-stickers",
320
+ fromB64("I3Jla2xhbW5pLWJveA=="),
321
+ fromB64("LnJla2xhbWEtbWVnYWJvYXJk"),
322
+ ".sklik",
323
+ fromB64("W2lkXj0ic2tsaWtSZWtsYW1hIl0="),
324
+ ],
325
+ easyListDutch: [
326
+ fromB64("I2FkdmVydGVudGll"),
327
+ fromB64("I3ZpcEFkbWFya3RCYW5uZXJCbG9jaw=="),
328
+ ".adstekst",
329
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly94bHR1YmUubmwvY2xpY2svIl0="),
330
+ "#semilo-lrectangle",
331
+ ],
332
+ easyListGermany: [
333
+ "#SSpotIMPopSlider",
334
+ fromB64("LnNwb25zb3JsaW5rZ3J1ZW4="),
335
+ fromB64("I3dlcmJ1bmdza3k="),
336
+ fromB64("I3Jla2xhbWUtcmVjaHRzLW1pdHRl"),
337
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9iZDc0Mi5jb20vIl0="),
338
+ ],
339
+ easyListItaly: [
340
+ fromB64("LmJveF9hZHZfYW5udW5jaQ=="),
341
+ ".sb-box-pubbliredazionale",
342
+ fromB64("YVtocmVmXj0iaHR0cDovL2FmZmlsaWF6aW9uaWFkcy5zbmFpLml0LyJd"),
343
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZHNlcnZlci5odG1sLml0LyJd"),
344
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZmZpbGlhemlvbmlhZHMuc25haS5pdC8iXQ=="),
345
+ ],
346
+ easyListLithuania: [
347
+ fromB64("LnJla2xhbW9zX3RhcnBhcw=="),
348
+ fromB64("LnJla2xhbW9zX251b3JvZG9z"),
349
+ fromB64("aW1nW2FsdD0iUmVrbGFtaW5pcyBza3lkZWxpcyJd"),
350
+ fromB64("aW1nW2FsdD0iRGVkaWt1b3RpLmx0IHNlcnZlcmlhaSJd"),
351
+ fromB64("aW1nW2FsdD0iSG9zdGluZ2FzIFNlcnZlcmlhaS5sdCJd"),
352
+ ],
353
+ estonian: [fromB64("QVtocmVmKj0iaHR0cDovL3BheTRyZXN1bHRzMjQuZXUiXQ==")],
354
+ fanboyAnnoyances: [
355
+ "#ac-lre-player",
356
+ ".navigate-to-top",
357
+ "#subscribe_popup",
358
+ ".newsletter_holder",
359
+ "#back-top",
360
+ ],
361
+ fanboyAntiFacebook: [".util-bar-module-firefly-visible"],
362
+ fanboyEnhancedTrackers: [
363
+ ".open.pushModal",
364
+ "#issuem-leaky-paywall-articles-zero-remaining-nag",
365
+ "#sovrn_container",
366
+ 'div[class$="-hide"][zoompage-fontsize][style="display: block;"]',
367
+ ".BlockNag__Card",
368
+ ],
369
+ fanboySocial: [
370
+ "#FollowUs",
371
+ "#meteored_share",
372
+ "#social_follow",
373
+ ".article-sharer",
374
+ ".community__social-desc",
375
+ ],
376
+ frellwitSwedish: [
377
+ fromB64("YVtocmVmKj0iY2FzaW5vcHJvLnNlIl1bdGFyZ2V0PSJfYmxhbmsiXQ=="),
378
+ fromB64("YVtocmVmKj0iZG9rdG9yLXNlLm9uZWxpbmsubWUiXQ=="),
379
+ "article.category-samarbete",
380
+ fromB64("ZGl2LmhvbGlkQWRz"),
381
+ "ul.adsmodern",
382
+ ],
383
+ greekAdBlock: [
384
+ fromB64("QVtocmVmKj0iYWRtYW4ub3RlbmV0LmdyL2NsaWNrPyJd"),
385
+ fromB64("QVtocmVmKj0iaHR0cDovL2F4aWFiYW5uZXJzLmV4b2R1cy5nci8iXQ=="),
386
+ fromB64(
387
+ "QVtocmVmKj0iaHR0cDovL2ludGVyYWN0aXZlLmZvcnRobmV0LmdyL2NsaWNrPyJd"
388
+ ),
389
+ "DIV.agores300",
390
+ "TABLE.advright",
391
+ ],
392
+ hungarian: [
393
+ "#cemp_doboz",
394
+ ".optimonk-iframe-container",
395
+ fromB64("LmFkX19tYWlu"),
396
+ fromB64("W2NsYXNzKj0iR29vZ2xlQWRzIl0="),
397
+ "#hirdetesek_box",
398
+ ],
399
+ iDontCareAboutCookies: [
400
+ '.alert-info[data-block-track*="CookieNotice"]',
401
+ ".ModuleTemplateCookieIndicator",
402
+ ".o--cookies--container",
403
+ "#cookies-policy-sticky",
404
+ "#stickyCookieBar",
405
+ ],
406
+ icelandicAbp: [
407
+ fromB64(
408
+ "QVtocmVmXj0iL2ZyYW1ld29yay9yZXNvdXJjZXMvZm9ybXMvYWRzLmFzcHgiXQ=="
409
+ ),
410
+ ],
411
+ latvian: [
412
+ fromB64(
413
+ "YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiAxMjBweDsgaGVpZ2h0O" +
414
+ "iA0MHB4OyBvdmVyZmxvdzogaGlkZGVuOyBwb3NpdGlvbjogcmVsYXRpdmU7Il0="
415
+ ),
416
+ fromB64(
417
+ "YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiA4OHB4OyBoZWlnaHQ6I" +
418
+ "DMxcHg7IG92ZXJmbG93OiBoaWRkZW47IHBvc2l0aW9uOiByZWxhdGl2ZTsiXQ=="
419
+ ),
420
+ ],
421
+ listKr: [
422
+ fromB64("YVtocmVmKj0iLy9hZC5wbGFuYnBsdXMuY28ua3IvIl0="),
423
+ fromB64("I2xpdmVyZUFkV3JhcHBlcg=="),
424
+ fromB64("YVtocmVmKj0iLy9hZHYuaW1hZHJlcC5jby5rci8iXQ=="),
425
+ fromB64("aW5zLmZhc3R2aWV3LWFk"),
426
+ ".revenue_unit_item.dable",
427
+ ],
428
+ listeAr: [
429
+ fromB64("LmdlbWluaUxCMUFk"),
430
+ ".right-and-left-sponsers",
431
+ fromB64("YVtocmVmKj0iLmFmbGFtLmluZm8iXQ=="),
432
+ fromB64("YVtocmVmKj0iYm9vcmFxLm9yZyJd"),
433
+ fromB64("YVtocmVmKj0iZHViaXp6bGUuY29tL2FyLz91dG1fc291cmNlPSJd"),
434
+ ],
435
+ listeFr: [
436
+ fromB64("YVtocmVmXj0iaHR0cDovL3Byb21vLnZhZG9yLmNvbS8iXQ=="),
437
+ fromB64("I2FkY29udGFpbmVyX3JlY2hlcmNoZQ=="),
438
+ fromB64("YVtocmVmKj0id2Vib3JhbWEuZnIvZmNnaS1iaW4vIl0="),
439
+ ".site-pub-interstitiel",
440
+ 'div[id^="crt-"][data-criteo-id]',
441
+ ],
442
+ officialPolish: [
443
+ "#ceneo-placeholder-ceneo-12",
444
+ fromB64("W2hyZWZePSJodHRwczovL2FmZi5zZW5kaHViLnBsLyJd"),
445
+ fromB64(
446
+ "YVtocmVmXj0iaHR0cDovL2Fkdm1hbmFnZXIudGVjaGZ1bi5wbC9yZWRpcmVjdC8iXQ=="
447
+ ),
448
+ fromB64("YVtocmVmXj0iaHR0cDovL3d3dy50cml6ZXIucGwvP3V0bV9zb3VyY2UiXQ=="),
449
+ fromB64("ZGl2I3NrYXBpZWNfYWQ="),
450
+ ],
451
+ ro: [
452
+ fromB64("YVtocmVmXj0iLy9hZmZ0cmsuYWx0ZXgucm8vQ291bnRlci9DbGljayJd"),
453
+ fromB64(
454
+ "YVtocmVmXj0iaHR0cHM6Ly9ibGFja2ZyaWRheXNhbGVzLnJvL3Ryay9zaG9wLyJd"
455
+ ),
456
+ fromB64(
457
+ "YVtocmVmXj0iaHR0cHM6Ly9ldmVudC4ycGVyZm9ybWFudC5jb20vZXZlbnRzL2NsaWNrIl0="
458
+ ),
459
+ fromB64("YVtocmVmXj0iaHR0cHM6Ly9sLnByb2ZpdHNoYXJlLnJvLyJd"),
460
+ 'a[href^="/url/"]',
461
+ ],
462
+ ruAd: [
463
+ fromB64("YVtocmVmKj0iLy9mZWJyYXJlLnJ1LyJd"),
464
+ fromB64("YVtocmVmKj0iLy91dGltZy5ydS8iXQ=="),
465
+ fromB64("YVtocmVmKj0iOi8vY2hpa2lkaWtpLnJ1Il0="),
466
+ "#pgeldiz",
467
+ ".yandex-rtb-block",
468
+ ],
469
+ thaiAds: [
470
+ "a[href*=macau-uta-popup]",
471
+ fromB64("I2Fkcy1nb29nbGUtbWlkZGxlX3JlY3RhbmdsZS1ncm91cA=="),
472
+ fromB64("LmFkczMwMHM="),
473
+ ".bumq",
474
+ ".img-kosana",
475
+ ],
476
+ webAnnoyancesUltralist: [
477
+ "#mod-social-share-2",
478
+ "#social-tools",
479
+ fromB64("LmN0cGwtZnVsbGJhbm5lcg=="),
480
+ ".zergnet-recommend",
481
+ ".yt.btn-link.btn-md.btn",
482
+ ],
483
+ };
484
+ }
485
+
486
+ /**
487
+ * The order of the returned array means nothing (it's always sorted alphabetically).
488
+ *
489
+ * Notice that the source is slightly unstable.
490
+ * Safari provides a 2-taps way to disable all content blockers on a page temporarily.
491
+ * Also content blockers can be disabled permanently for a domain, but it requires 4 taps.
492
+ * So empty array shouldn't be treated as "no blockers", it should be treated as "no signal".
493
+ * If you are a website owner, don't make your visitors want to disable content blockers.
494
+ */
495
+ async function getDomBlockers(): Promise<any> {
496
+ if (!isApplicable()) {
497
+ return undefined;
498
+ }
499
+
500
+ const filters = getFilters();
501
+ const filterNames = Object.keys(filters) as Array<keyof typeof filters>;
502
+ const allSelectors = ([] as string[]).concat(
503
+ ...filterNames.map((filterName) => filters[filterName])
504
+ );
505
+ const blockedSelectors = await getBlockedSelectors(allSelectors);
506
+
507
+ const activeBlockers = filterNames.filter((filterName) => {
508
+ const selectors = filters[filterName];
509
+ const blockedCount = countTruthy(
510
+ selectors.map((selector) => blockedSelectors[selector])
511
+ );
512
+ return blockedCount > selectors.length * 0.6;
513
+ });
514
+ activeBlockers.sort();
515
+
516
+ return activeBlockers;
517
+ }
518
+
519
+ function isApplicable(): boolean {
520
+ // Safari (desktop and mobile) and all Android browsers keep content blockers in both regular and private mode
521
+ return isWebKit() || isAndroid();
522
+ }
523
+
524
+ async function getBlockedSelectors<T extends string>(
525
+ selectors: readonly T[]
526
+ ): Promise<{ [K in T]?: true }> {
527
+ const d = document;
528
+ const root = d.createElement("div");
529
+ const elements = new Array<HTMLElement>(selectors.length);
530
+ const blockedSelectors: { [K in T]?: true } = {}; // Set() isn't used just in case somebody need older browser support
531
+
532
+ forceShow(root);
533
+
534
+ // First create all elements that can be blocked. If the DOM steps below are done in a single cycle,
535
+ // browser will alternate tree modification and layout reading, that is very slow.
536
+ for (let i = 0; i < selectors.length; ++i) {
537
+ const element = selectorToElement(selectors[i]);
538
+ if (element.tagName === "DIALOG") {
539
+ (element as HTMLDialogElement).show();
540
+ }
541
+ const holder = d.createElement("div"); // Protects from unwanted effects of `+` and `~` selectors of filters
542
+ forceShow(holder);
543
+ holder.appendChild(element);
544
+ root.appendChild(holder);
545
+ elements[i] = element;
546
+ }
547
+
548
+ // document.body can be null while the page is loading
549
+ while (!d.body) {
550
+ await wait(50);
551
+ }
552
+ d.body.appendChild(root);
553
+
554
+ try {
555
+ // Then check which of the elements are blocked
556
+ for (let i = 0; i < selectors.length; ++i) {
557
+ if (!elements[i].offsetParent) {
558
+ blockedSelectors[selectors[i]] = true;
559
+ }
560
+ }
561
+ } finally {
562
+ // Then remove the elements
563
+ root.parentNode?.removeChild(root);
564
+ }
565
+
566
+ return blockedSelectors;
567
+ }
568
+
569
+ function forceShow(element: HTMLElement) {
570
+ element.style.setProperty("visibility", "hidden", "important");
571
+ element.style.setProperty("display", "block", "important");
572
+ }
573
+
574
+ includeComponent("domBlockers", getDomBlockers);
575
+ includeComponent("vendorFlavour", getVendorFlavors);
576
+ includeComponent("monochrome", getMonochromeDepth);
577
+ includeComponent("forcedColors", areColorsForced);
578
+ includeComponent("colorGamut", getColorGamut);
579
+ includeComponent("osCpu", getOsCpu);
580
+ includeComponent("audioLatency", getAudioContextBaseLatency);
581
+