@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,143 @@
1
+ import { componentInterface, includeComponent } from '../../factory'
2
+ import { ephemeralIFrame } from '../../utils/ephemeralIFrame'
3
+ import { getBrowserName } from '../system/browser'
4
+
5
+
6
+
7
+ const availableFonts = [
8
+ 'Arial',
9
+ 'Arial Black',
10
+ 'Arial Narrow',
11
+ 'Arial Rounded MT',
12
+ 'Arimo',
13
+ 'Archivo',
14
+ 'Barlow',
15
+ 'Bebas Neue',
16
+ 'Bitter',
17
+ 'Bookman',
18
+ 'Calibri',
19
+ 'Cabin',
20
+ 'Candara',
21
+ 'Century',
22
+ 'Century Gothic',
23
+ 'Comic Sans MS',
24
+ 'Constantia',
25
+ 'Courier',
26
+ 'Courier New',
27
+ 'Crimson Text',
28
+ 'DM Mono',
29
+ 'DM Sans',
30
+ 'DM Serif Display',
31
+ 'DM Serif Text',
32
+ 'Dosis',
33
+ 'Droid Sans',
34
+ 'Exo',
35
+ 'Fira Code',
36
+ 'Fira Sans',
37
+ 'Franklin Gothic Medium',
38
+ 'Garamond',
39
+ 'Geneva',
40
+ 'Georgia',
41
+ 'Gill Sans',
42
+ 'Helvetica',
43
+ 'Impact',
44
+ 'Inconsolata',
45
+ 'Indie Flower',
46
+ 'Inter',
47
+ 'Josefin Sans',
48
+ 'Karla',
49
+ 'Lato',
50
+ 'Lexend',
51
+ 'Lucida Bright',
52
+ 'Lucida Console',
53
+ 'Lucida Sans Unicode',
54
+ 'Manrope',
55
+ 'Merriweather',
56
+ 'Merriweather Sans',
57
+ 'Montserrat',
58
+ 'Myriad',
59
+ 'Noto Sans',
60
+ 'Nunito',
61
+ 'Nunito Sans',
62
+ 'Open Sans',
63
+ 'Optima',
64
+ 'Orbitron',
65
+ 'Oswald',
66
+ 'Pacifico',
67
+ 'Palatino',
68
+ 'Perpetua',
69
+ 'PT Sans',
70
+ 'PT Serif',
71
+ 'Poppins',
72
+ 'Prompt',
73
+ 'Public Sans',
74
+ 'Quicksand',
75
+ 'Rajdhani',
76
+ 'Recursive',
77
+ 'Roboto',
78
+ 'Roboto Condensed',
79
+ 'Rockwell',
80
+ 'Rubik',
81
+ 'Segoe Print',
82
+ 'Segoe Script',
83
+ 'Segoe UI',
84
+ 'Sora',
85
+ 'Source Sans Pro',
86
+ 'Space Mono',
87
+ 'Tahoma',
88
+ 'Taviraj',
89
+ 'Times',
90
+ 'Times New Roman',
91
+ 'Titillium Web',
92
+ 'Trebuchet MS',
93
+ 'Ubuntu',
94
+ 'Varela Round',
95
+ 'Verdana',
96
+ 'Work Sans',
97
+ ];
98
+
99
+ const baseFonts = ['monospace', 'sans-serif', 'serif'];
100
+
101
+ export default function getFontMetrics(): Promise<componentInterface> {
102
+
103
+ return new Promise((resolve, reject) => {
104
+ try {
105
+
106
+ ephemeralIFrame(async ({ iframe }) => {
107
+
108
+ const canvas = iframe.createElement('canvas');
109
+ const ctx = canvas.getContext('2d');
110
+
111
+ const defaultWidths: number[] = baseFonts.map((font) => {
112
+ return measureSingleFont(ctx, font)
113
+ })
114
+
115
+ let results: {[k: string]: any} = {};
116
+ availableFonts.forEach((font) => {
117
+ const fontWidth = measureSingleFont(ctx, font);
118
+ if (!defaultWidths.includes(fontWidth))
119
+ results[font] = fontWidth;
120
+ });
121
+
122
+ resolve(results);
123
+ })
124
+
125
+
126
+ } catch (error) {
127
+ reject({'error': 'unsupported'})
128
+ }
129
+ });
130
+ };
131
+
132
+
133
+ function measureSingleFont(ctx: CanvasRenderingContext2D | null, font: string): number {
134
+ if (!ctx) {
135
+ throw new Error('Canvas context not supported');
136
+ }
137
+ const text: string = "WwMmLli0Oo";
138
+ ctx.font = `72px ${font}`; // Set a default font size
139
+ return ctx.measureText(text).width;
140
+ }
141
+
142
+ if (getBrowserName() != 'Firefox')
143
+ includeComponent('fonts', getFontMetrics);
@@ -0,0 +1,66 @@
1
+ import { componentInterface, includeComponent } from '../../factory'
2
+
3
+ function getHardwareInfo(): Promise<componentInterface> {
4
+ return new Promise((resolve) => {
5
+ const memoryInfo = (window.performance && (window.performance as any).memory ) ? (window.performance as any).memory : 0
6
+ resolve(
7
+ {
8
+ 'videocard': getVideoCard(),
9
+ 'architecture': getArchitecture(),
10
+ 'jsHeapSizeLimit': memoryInfo.jsHeapSizeLimit || 0
11
+ }
12
+ )
13
+ });
14
+ }
15
+
16
+ function getVideoCard(): componentInterface | string {
17
+ const canvas = document.createElement('canvas');
18
+ const gl = canvas.getContext('webgl') ?? canvas.getContext('experimental-webgl');
19
+
20
+ if (gl && 'getParameter' in gl) {
21
+ try {
22
+ // Try standard parameters first
23
+ const vendor = (gl.getParameter(gl.VENDOR) || '').toString();
24
+ const renderer = (gl.getParameter(gl.RENDERER) || '').toString();
25
+
26
+ let result: componentInterface = {
27
+ vendor: vendor,
28
+ renderer: renderer,
29
+ version: (gl.getParameter(gl.VERSION) || '').toString(),
30
+ shadingLanguageVersion: (gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || '').toString(),
31
+ };
32
+
33
+ // Only try debug info if needed and available
34
+
35
+ const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
36
+ if (debugInfo) {
37
+ const vendorUnmasked = (gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '').toString();
38
+ const rendererUnmasked = (gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '').toString();
39
+
40
+ // Only add unmasked values if they exist
41
+ if (vendorUnmasked) {
42
+ result.vendorUnmasked = vendorUnmasked;
43
+ }
44
+ if (rendererUnmasked) {
45
+ result.rendererUnmasked = rendererUnmasked;
46
+ }
47
+ }
48
+
49
+ return result;
50
+ } catch (error) {
51
+ // fail silently
52
+ }
53
+ }
54
+ return "undefined";
55
+ }
56
+
57
+ function getArchitecture(): number {
58
+ const f = new Float32Array(1);
59
+ const u8 = new Uint8Array(f.buffer);
60
+ f[0] = Infinity;
61
+ f[0] = f[0] - f[0];
62
+
63
+ return u8[3];
64
+ }
65
+
66
+ includeComponent('hardware', getHardwareInfo);
@@ -0,0 +1,14 @@
1
+ import './audio/audio'
2
+ import './canvas/canvas'
3
+ import './fonts/fonts'
4
+ import './hardware/hardware'
5
+ import './locales/locales'
6
+ import './permissions/permissions'
7
+ import './screen/screen'
8
+ import './screen/screenResolution'
9
+ import './webgl/webgl'
10
+ import './plugins/plugins'
11
+ import './system/system'
12
+ import './system/emoji'
13
+ import './math/math'
14
+ import './extra/extra'
@@ -0,0 +1,21 @@
1
+ import { componentInterface, includeComponent } from '../../factory'
2
+
3
+ function getLocales(): Promise<componentInterface> {
4
+ return new Promise((resolve) => {
5
+ resolve(
6
+ {
7
+ 'languages': getUserLanguage(),
8
+ 'timezone': getUserTimezone()
9
+ });
10
+ });
11
+ }
12
+
13
+ function getUserLanguage(): string {
14
+ return navigator.language;
15
+ }
16
+
17
+ function getUserTimezone(): string {
18
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
19
+ }
20
+
21
+ includeComponent('locales', getLocales);
@@ -0,0 +1,39 @@
1
+ import { componentInterface, includeComponent } from '../../factory'
2
+
3
+ const getMathInfo = async (): Promise<componentInterface> => {
4
+ return {
5
+ acos: Math.acos(0.5),
6
+ asin: integrate(Math.asin, -1, 1, 97),
7
+ atan: integrate(Math.atan, -1, 1, 97),
8
+ cos: integrate(Math.cos, 0, Math.PI, 97),
9
+ cosh: Math.cosh(9/7),
10
+ e: Math.E,
11
+ largeCos: Math.cos(1e20),
12
+ largeSin: Math.sin(1e20),
13
+ largeTan: Math.tan(1e20),
14
+ log: Math.log(1000),
15
+ pi: Math.PI,
16
+ sin: integrate(Math.sin, -Math.PI, Math.PI, 97),
17
+ sinh: integrate(Math.sinh, -9/7, 7/9, 97),
18
+ sqrt: Math.sqrt(2),
19
+ tan: integrate(Math.tan, 0, 2 * Math.PI, 97),
20
+ tanh: integrate(Math.tanh, -9/7, 7/9, 97),
21
+ }
22
+ }
23
+
24
+ /** This might be a little excessive, but I wasn't sure what number to pick for some of the
25
+ * trigonometric functions. Using an integral here, so a few numbers are calculated. However,
26
+ * I do this mainly for those integrals that sum up to a small value, otherwise there's no point.
27
+ */
28
+
29
+ const integrate = (f: (x: number) => number, a: number, b: number, n: number): number => {
30
+ const h = (b - a) / n;
31
+ let sum = 0;
32
+ for (let i = 0; i < n; i++) {
33
+ const x = a + (i + 0.5) * h;
34
+ sum += f(x);
35
+ }
36
+ return sum * h;
37
+ };
38
+
39
+ includeComponent('math', getMathInfo);
@@ -0,0 +1,60 @@
1
+ import { componentInterface, includeComponent } from '../../factory';
2
+ import { mostFrequentValuesInArrayOfDictionaries } from '../../utils/getMostFrequent';
3
+ import { options } from '../../modules/options';
4
+
5
+ let permission_keys: PermissionName[];
6
+ function initializePermissionKeys() {
7
+ permission_keys = options?.permissions_to_check || [
8
+ 'accelerometer',
9
+ 'accessibility', 'accessibility-events',
10
+ 'ambient-light-sensor',
11
+ 'background-fetch',
12
+ 'background-sync',
13
+ 'bluetooth',
14
+ 'clipboard-read',
15
+ 'clipboard-write',
16
+ 'device-info',
17
+ 'display-capture',
18
+ 'gyroscope',
19
+ 'local-fonts',
20
+ 'magnetometer',
21
+ 'midi',
22
+ 'nfc', 'notifications',
23
+ 'payment-handler',
24
+ 'persistent-storage',
25
+ 'speaker', 'storage-access',
26
+ 'top-level-storage-access',
27
+ 'window-management',
28
+ 'query',
29
+ ] as PermissionName[];
30
+ }
31
+
32
+ export default async function getBrowserPermissions(): Promise<componentInterface> {
33
+ initializePermissionKeys();
34
+ const permissionPromises: Promise<componentInterface>[] = Array.from({length: options?.retries || 3}, () => getBrowserPermissionsOnce() );
35
+ return Promise.all(permissionPromises).then((resolvedPermissions) => {
36
+ const permission = mostFrequentValuesInArrayOfDictionaries(resolvedPermissions, permission_keys);
37
+ return permission;
38
+ });
39
+ }
40
+
41
+ async function getBrowserPermissionsOnce(): Promise<componentInterface> {
42
+
43
+ const permissionStatus: { [key: string]: string } = {};
44
+
45
+ for (const feature of permission_keys) {
46
+ try {
47
+ // Request permission status for each feature
48
+ const status = await navigator.permissions.query({ name: feature });
49
+
50
+ // Assign permission status to the object
51
+ permissionStatus[feature] = status.state.toString();
52
+ } catch (error) {
53
+ // In case of errors (unsupported features, etc.), do nothing. Not listing them is the same as not supported
54
+ }
55
+ }
56
+
57
+ return permissionStatus;
58
+ }
59
+
60
+ includeComponent("permissions", getBrowserPermissions);
@@ -0,0 +1,22 @@
1
+ import { componentInterface, includeComponent } from '../../factory'
2
+
3
+ export default function getInstalledPlugins(): Promise<componentInterface> {
4
+ const plugins: string[] = [];
5
+
6
+ if (navigator.plugins) {
7
+ for (let i = 0; i < navigator.plugins.length; i++) {
8
+ const plugin = navigator.plugins[i];
9
+ plugins.push([plugin.name, plugin.filename, plugin.description ].join("|"));
10
+ }
11
+ }
12
+
13
+ return new Promise((resolve) => {
14
+ resolve(
15
+ {
16
+ 'plugins': plugins
17
+ }
18
+ );
19
+ });
20
+ }
21
+
22
+ includeComponent('plugins', getInstalledPlugins);
@@ -0,0 +1,13 @@
1
+ import { componentInterface, includeComponent } from '../../factory';
2
+
3
+ function screenDetails(): Promise<componentInterface> {
4
+ return new Promise((resolve) => {
5
+ resolve(
6
+ {
7
+ 'colorDepth': screen.colorDepth,
8
+ }
9
+ );
10
+ });
11
+ }
12
+
13
+ includeComponent('screen', screenDetails);
@@ -0,0 +1,45 @@
1
+ import { includeComponent } from "../../factory";
2
+ import {
3
+ isSafariWebKit,
4
+ isWebKit,
5
+ isWebKit616OrNewer,
6
+ } from "../../utils/browser_";
7
+ import { replaceNaN, toInt } from "../../utils/data";
8
+
9
+ type ScreenResolution = [number | null, number | null];
10
+
11
+ /**
12
+ * A version of the entropy source with stabilization to make it suitable for static fingerprinting.
13
+ * The window resolution is always the document size in private mode of Safari 17,
14
+ * so the window resolution is not used in Safari 17.
15
+ */
16
+ export default async function getScreenResolution(): Promise<any> {
17
+ if (isWebKit() && isWebKit616OrNewer() && isSafariWebKit()) {
18
+ return [];
19
+ }
20
+
21
+ return getUnstableScreenResolution();
22
+ }
23
+
24
+ /**
25
+ * A version of the entropy source without stabilization.
26
+ *
27
+ * Warning for package users:
28
+ * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
29
+ */
30
+ export function getUnstableScreenResolution(): ScreenResolution {
31
+ const s = screen;
32
+
33
+ // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
34
+ // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
35
+ // Some browsers even return screen resolution as not numbers.
36
+ const parseDimension = (value: unknown) => replaceNaN(toInt(value), null);
37
+ const dimensions = [
38
+ parseDimension(s.width),
39
+ parseDimension(s.height),
40
+ ] as ScreenResolution;
41
+ dimensions.sort().reverse();
42
+ return dimensions;
43
+ }
44
+
45
+ includeComponent("screenResolution", getScreenResolution);