content-security-toolkit 1.0.0

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 (162) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +171 -0
  3. package/dist/config/default-extensions-config.json +103 -0
  4. package/dist/core/ContentProtector.d.ts +63 -0
  5. package/dist/core/ContentProtector.js +279 -0
  6. package/dist/core/index.d.ts +1 -0
  7. package/dist/core/index.js +2 -0
  8. package/dist/core/mediator/ContentProtectionMediator.d.ts +86 -0
  9. package/dist/core/mediator/ContentProtectionMediator.js +238 -0
  10. package/dist/core/mediator/eventDataTypes.d.ts +205 -0
  11. package/dist/core/mediator/eventDataTypes.js +23 -0
  12. package/dist/core/mediator/handlers/abstractEventHandler.d.ts +67 -0
  13. package/dist/core/mediator/handlers/abstractEventHandler.js +106 -0
  14. package/dist/core/mediator/handlers/baseEventHandler.d.ts +65 -0
  15. package/dist/core/mediator/handlers/baseEventHandler.js +99 -0
  16. package/dist/core/mediator/handlers/devToolsEventHandler.d.ts +9 -0
  17. package/dist/core/mediator/handlers/devToolsEventHandler.js +95 -0
  18. package/dist/core/mediator/handlers/eventHandlerRegistry.d.ts +9 -0
  19. package/dist/core/mediator/handlers/eventHandlerRegistry.js +34 -0
  20. package/dist/core/mediator/handlers/extensionEventHandlers.d.ts +40 -0
  21. package/dist/core/mediator/handlers/extensionEventHandlers.js +140 -0
  22. package/dist/core/mediator/handlers/iFrameEventHandlers.d.ts +27 -0
  23. package/dist/core/mediator/handlers/iFrameEventHandlers.js +93 -0
  24. package/dist/core/mediator/handlers/index.d.ts +9 -0
  25. package/dist/core/mediator/handlers/index.js +34 -0
  26. package/dist/core/mediator/handlers/screenShotEventHandlers.d.ts +34 -0
  27. package/dist/core/mediator/handlers/screenShotEventHandlers.js +111 -0
  28. package/dist/core/mediator/protection-event.d.ts +94 -0
  29. package/dist/core/mediator/protection-event.js +43 -0
  30. package/dist/core/mediator/types.d.ts +105 -0
  31. package/dist/core/mediator/types.js +1 -0
  32. package/dist/index.d.ts +4 -0
  33. package/dist/index.js +5 -0
  34. package/dist/strategies/AbstractStrategy.d.ts +152 -0
  35. package/dist/strategies/AbstractStrategy.js +296 -0
  36. package/dist/strategies/AbstractStrategy.mediator.d.ts +162 -0
  37. package/dist/strategies/AbstractStrategy.mediator.js +349 -0
  38. package/dist/strategies/ClipboardStrategy.d.ts +67 -0
  39. package/dist/strategies/ClipboardStrategy.js +291 -0
  40. package/dist/strategies/ContextMenuStrategy.d.ts +60 -0
  41. package/dist/strategies/ContextMenuStrategy.js +454 -0
  42. package/dist/strategies/DevToolsStrategy copy.d.ts +85 -0
  43. package/dist/strategies/DevToolsStrategy copy.js +362 -0
  44. package/dist/strategies/DevToolsStrategy-detectorManager.d.ts +70 -0
  45. package/dist/strategies/DevToolsStrategy-detectorManager.js +309 -0
  46. package/dist/strategies/DevToolsStrategy-simple.d.ts +75 -0
  47. package/dist/strategies/DevToolsStrategy-simple.js +366 -0
  48. package/dist/strategies/DevToolsStrategy.d.ts +55 -0
  49. package/dist/strategies/DevToolsStrategy.js +314 -0
  50. package/dist/strategies/ExtensionStrategy.d.ts +66 -0
  51. package/dist/strategies/ExtensionStrategy.js +486 -0
  52. package/dist/strategies/IFrameStrategy.d.ts +49 -0
  53. package/dist/strategies/IFrameStrategy.js +255 -0
  54. package/dist/strategies/KeyboardStrategy.d.ts +35 -0
  55. package/dist/strategies/KeyboardStrategy.js +130 -0
  56. package/dist/strategies/PrintStrategy.d.ts +47 -0
  57. package/dist/strategies/PrintStrategy.js +201 -0
  58. package/dist/strategies/ScreenshotStrategy.d.ts +90 -0
  59. package/dist/strategies/ScreenshotStrategy.js +488 -0
  60. package/dist/strategies/SelectionStrategy.d.ts +49 -0
  61. package/dist/strategies/SelectionStrategy.js +216 -0
  62. package/dist/strategies/StrategyRegistry.d.ts +133 -0
  63. package/dist/strategies/StrategyRegistry.js +379 -0
  64. package/dist/strategies/WatermarkStrategy.d.ts +47 -0
  65. package/dist/strategies/WatermarkStrategy.js +273 -0
  66. package/dist/strategies/index.d.ts +9 -0
  67. package/dist/strategies/index.js +10 -0
  68. package/dist/types/index.d.ts +271 -0
  69. package/dist/types/index.js +16 -0
  70. package/dist/utils/DOMObserver.d.ts +68 -0
  71. package/dist/utils/DOMObserver.js +134 -0
  72. package/dist/utils/base/LoggableComponent.d.ts +62 -0
  73. package/dist/utils/base/LoggableComponent.js +95 -0
  74. package/dist/utils/debuggerDetector/debuggerDetectionWorker.d.ts +6 -0
  75. package/dist/utils/debuggerDetector/debuggerDetectionWorker.js +24 -0
  76. package/dist/utils/debuggerDetector/debuggerDetector.d.ts +55 -0
  77. package/dist/utils/debuggerDetector/debuggerDetector.js +158 -0
  78. package/dist/utils/debuggerDetector/firefoxDetector.d.ts +8 -0
  79. package/dist/utils/debuggerDetector/firefoxDetector.js +64 -0
  80. package/dist/utils/detection.d.ts +29 -0
  81. package/dist/utils/detection.js +267 -0
  82. package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +105 -0
  83. package/dist/utils/detectors/AbstractDevToolsDetector.js +136 -0
  84. package/dist/utils/detectors/dateToStringDetector.d.ts +43 -0
  85. package/dist/utils/detectors/dateToStringDetector.js +96 -0
  86. package/dist/utils/detectors/debugLibDetector.d.ts +64 -0
  87. package/dist/utils/detectors/debugLibDetector.js +195 -0
  88. package/dist/utils/detectors/debuggerDetectionWorker.d.ts +6 -0
  89. package/dist/utils/detectors/debuggerDetectionWorker.js +24 -0
  90. package/dist/utils/detectors/debuggerDetector.d.ts +51 -0
  91. package/dist/utils/detectors/debuggerDetector.js +211 -0
  92. package/dist/utils/detectors/defineGetterDetector.d.ts +48 -0
  93. package/dist/utils/detectors/defineGetterDetector.js +150 -0
  94. package/dist/utils/detectors/detectorInterface.d.ts +36 -0
  95. package/dist/utils/detectors/detectorInterface.js +1 -0
  96. package/dist/utils/detectors/devToolsDetectorManager.d.ts +88 -0
  97. package/dist/utils/detectors/devToolsDetectorManager.js +246 -0
  98. package/dist/utils/detectors/firefoxDetector.d.ts +8 -0
  99. package/dist/utils/detectors/firefoxDetector.js +64 -0
  100. package/dist/utils/detectors/funcToStringDetector.d.ts +43 -0
  101. package/dist/utils/detectors/funcToStringDetector.js +90 -0
  102. package/dist/utils/detectors/regToStringDetector.d.ts +43 -0
  103. package/dist/utils/detectors/regToStringDetector.js +129 -0
  104. package/dist/utils/detectors/sizeDetector.d.ts +54 -0
  105. package/dist/utils/detectors/sizeDetector.js +134 -0
  106. package/dist/utils/detectors/timingDetector.d.ts +55 -0
  107. package/dist/utils/detectors/timingDetector.js +143 -0
  108. package/dist/utils/dom.d.ts +20 -0
  109. package/dist/utils/dom.js +83 -0
  110. package/dist/utils/environment.d.ts +29 -0
  111. package/dist/utils/environment.js +267 -0
  112. package/dist/utils/eventManager.d.ts +167 -0
  113. package/dist/utils/eventManager.js +556 -0
  114. package/dist/utils/index.d.ts +2 -0
  115. package/dist/utils/index.js +3 -0
  116. package/dist/utils/intervalManager.d.ts +96 -0
  117. package/dist/utils/intervalManager.js +229 -0
  118. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.d.ts +41 -0
  119. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.js +135 -0
  120. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.d.ts +18 -0
  121. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.js +195 -0
  122. package/dist/utils/logging/LogLevel.d.ts +21 -0
  123. package/dist/utils/logging/LogLevel.js +46 -0
  124. package/dist/utils/logging/LoggingConfig.d.ts +68 -0
  125. package/dist/utils/logging/LoggingConfig.js +64 -0
  126. package/dist/utils/logging/LoggingFactory.d.ts +22 -0
  127. package/dist/utils/logging/LoggingFactory.js +61 -0
  128. package/dist/utils/logging/LoggingService.d.ts +235 -0
  129. package/dist/utils/logging/LoggingService.js +385 -0
  130. package/dist/utils/logging/SimpleLoggingService.d.ts +39 -0
  131. package/dist/utils/logging/SimpleLoggingService.js +58 -0
  132. package/dist/utils/logging/advanced/LogLevel.d.ts +21 -0
  133. package/dist/utils/logging/advanced/LogLevel.js +46 -0
  134. package/dist/utils/logging/advanced/LoggingConfig.d.ts +68 -0
  135. package/dist/utils/logging/advanced/LoggingConfig.js +64 -0
  136. package/dist/utils/logging/advanced/LoggingFactory.d.ts +22 -0
  137. package/dist/utils/logging/advanced/LoggingFactory.js +61 -0
  138. package/dist/utils/logging/advanced/LoggingService.d.ts +235 -0
  139. package/dist/utils/logging/advanced/LoggingService.js +385 -0
  140. package/dist/utils/logging/simple/Loggable.d.ts +33 -0
  141. package/dist/utils/logging/simple/Loggable.js +1 -0
  142. package/dist/utils/logging/simple/LoggingDelegate.d.ts +42 -0
  143. package/dist/utils/logging/simple/LoggingDelegate.js +53 -0
  144. package/dist/utils/logging/simple/SimpleLoggingService.d.ts +39 -0
  145. package/dist/utils/logging/simple/SimpleLoggingService.js +58 -0
  146. package/dist/utils/orientation.d.ts +15 -0
  147. package/dist/utils/orientation.js +32 -0
  148. package/dist/utils/protectedContentManager-simple.d.ts +86 -0
  149. package/dist/utils/protectedContentManager-simple.js +180 -0
  150. package/dist/utils/protectedContentManager.d.ts +162 -0
  151. package/dist/utils/protectedContentManager.js +427 -0
  152. package/dist/utils/screenshotDetector.d.ts +72 -0
  153. package/dist/utils/screenshotDetector.js +179 -0
  154. package/dist/utils/securityOverlayManager-observer-pause.d.ts +283 -0
  155. package/dist/utils/securityOverlayManager-observer-pause.js +878 -0
  156. package/dist/utils/securityOverlayManager-simple.d.ts +197 -0
  157. package/dist/utils/securityOverlayManager-simple.js +552 -0
  158. package/dist/utils/securityOverlayManager.d.ts +260 -0
  159. package/dist/utils/securityOverlayManager.js +774 -0
  160. package/dist/utils/timeoutManager.d.ts +55 -0
  161. package/dist/utils/timeoutManager.js +121 -0
  162. package/package.json +54 -0
@@ -0,0 +1,51 @@
1
+ import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
2
+ import type { DevToolsDetectorOptions } from "./detectorInterface";
3
+ /**
4
+ * Utility class for detecting DevTools using a Web Worker
5
+ * This approach works across browsers and provides immediate feedback
6
+ */
7
+ export interface DebuggerDetectorOptions extends DevToolsDetectorOptions {
8
+ /**
9
+ * Timeout duration in milliseconds
10
+ * If the worker doesn't respond within this time, DevTools is considered open
11
+ */
12
+ timeoutDuration?: number;
13
+ }
14
+ export declare class DebuggerDetector extends AbstractDevToolsDetector {
15
+ private worker;
16
+ private timeoutId;
17
+ private timeoutDuration;
18
+ private isInitialized;
19
+ private initializationAttempts;
20
+ private maxInitAttempts;
21
+ /**
22
+ * Create a new DebuggerDetector
23
+ * @param options Configuration options
24
+ */
25
+ constructor(options?: DebuggerDetectorOptions);
26
+ /**
27
+ * Initialize the worker for DevTools detection
28
+ */
29
+ private initWorker;
30
+ /**
31
+ * Perform a test check to ensure the worker is functioning correctly
32
+ */
33
+ private performTestCheck;
34
+ /**
35
+ * Check if DevTools is open
36
+ */
37
+ checkDevTools(): void;
38
+ /**
39
+ * Terminate the worker and clean up resources
40
+ */
41
+ private terminateWorker;
42
+ /**
43
+ * Clean up resources
44
+ */
45
+ dispose(): void;
46
+ /**
47
+ * Check if this detector is supported in the current browser
48
+ * @returns True if supported
49
+ */
50
+ static isSupported(): boolean;
51
+ }
@@ -0,0 +1,211 @@
1
+ import { getBrowser, isBrowser, isMobile } from "../environment";
2
+ import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
3
+ export class DebuggerDetector extends AbstractDevToolsDetector {
4
+ /**
5
+ * Create a new DebuggerDetector
6
+ * @param options Configuration options
7
+ */
8
+ constructor(options = {}) {
9
+ super("DebuggerDetector", options);
10
+ this.worker = null;
11
+ this.timeoutId = null;
12
+ this.isInitialized = false;
13
+ this.initializationAttempts = 0;
14
+ this.maxInitAttempts = 3;
15
+ this.timeoutDuration = options.timeoutDuration || 500;
16
+ // Delay worker initialization to avoid issues during page load
17
+ setTimeout(() => {
18
+ this.initWorker();
19
+ }, 100);
20
+ this.logger.log(`Initialized with timeout duration: ${this.timeoutDuration}ms`);
21
+ }
22
+ /**
23
+ * Initialize the worker for DevTools detection
24
+ */
25
+ initWorker() {
26
+ if (this.isInitialized || this.initializationAttempts >= this.maxInitAttempts)
27
+ return;
28
+ this.initializationAttempts++;
29
+ this.safeExecute("initWorker", DetectorErrorType.INITIALIZATION_ERROR, () => {
30
+ // Create a blob URL for the worker script instead of using a file URL
31
+ // This avoids MIME type issues with server responses
32
+ const workerScript = `
33
+ // Worker script for DevTools detection
34
+ self.onmessage = function(e) {
35
+ if (e.data === "checkDevTools") {
36
+ // Send immediate response (opening heartbeat)
37
+ self.postMessage("heartbeatStart");
38
+
39
+ // This will pause execution if DevTools is open
40
+ debugger;
41
+
42
+ // If we reach here without significant delay, DevTools is closed
43
+ self.postMessage("heartbeatEnd");
44
+ }
45
+ };
46
+ `;
47
+ // Create a blob URL from the script
48
+ const blob = new Blob([workerScript], { type: "application/javascript" });
49
+ const workerUrl = URL.createObjectURL(blob);
50
+ // Create the worker using the blob URL
51
+ this.worker = new Worker(workerUrl);
52
+ this.worker.onmessage = (e) => {
53
+ if (e.data === "heartbeatStart") {
54
+ // First heartbeat received, now waiting for second
55
+ this.logger.log("Received opening heartbeat");
56
+ }
57
+ else if (e.data === "heartbeatEnd") {
58
+ // Second heartbeat received, DevTools is closed
59
+ if (this.timeoutId !== null) {
60
+ clearTimeout(this.timeoutId);
61
+ this.timeoutId = null;
62
+ }
63
+ this.isChecking = false;
64
+ this.updateDevToolsState(false);
65
+ }
66
+ };
67
+ this.worker.onerror = (error) => {
68
+ this.logger.error("Worker error:", error);
69
+ this.isChecking = false;
70
+ // Try to recreate the worker
71
+ this.terminateWorker();
72
+ // Retry initialization with exponential backoff
73
+ setTimeout(() => {
74
+ this.initWorker();
75
+ }, Math.min(1000 * Math.pow(2, this.initializationAttempts - 1), 10000));
76
+ };
77
+ // Mark as initialized
78
+ this.isInitialized = true;
79
+ // Perform a test check to ensure everything is working
80
+ setTimeout(() => {
81
+ this.performTestCheck();
82
+ }, 200);
83
+ });
84
+ }
85
+ /**
86
+ * Perform a test check to ensure the worker is functioning correctly
87
+ */
88
+ performTestCheck() {
89
+ if (!this.worker || !this.isInitialized)
90
+ return;
91
+ this.safeExecute("performTestCheck", DetectorErrorType.DETECTION_ERROR, () => {
92
+ let testTimeoutId = null;
93
+ let testCompleted = false;
94
+ // Send message to worker
95
+ this.worker.postMessage("checkDevTools");
96
+ // Set a short timeout
97
+ testTimeoutId = window.setTimeout(() => {
98
+ // If we reach here and test isn't completed, something might be wrong
99
+ if (!testCompleted) {
100
+ this.logger.log("Test check timed out, worker might not be responding correctly");
101
+ }
102
+ testTimeoutId = null;
103
+ }, 100);
104
+ // Set up a one-time message handler for the test
105
+ const originalOnMessage = this.worker.onmessage;
106
+ this.worker.onmessage = (e) => {
107
+ if (e.data === "heartbeatEnd") {
108
+ testCompleted = true;
109
+ if (testTimeoutId !== null) {
110
+ clearTimeout(testTimeoutId);
111
+ testTimeoutId = null;
112
+ }
113
+ this.logger.log("Test check completed successfully");
114
+ // Restore original handler
115
+ this.worker.onmessage = originalOnMessage;
116
+ }
117
+ else {
118
+ // Pass through to original handler
119
+ if (originalOnMessage) {
120
+ originalOnMessage.call(this.worker, e);
121
+ }
122
+ }
123
+ };
124
+ });
125
+ }
126
+ /**
127
+ * Check if DevTools is open
128
+ */
129
+ checkDevTools() {
130
+ if (this.isChecking || !this.worker || !this.isInitialized)
131
+ return;
132
+ this.isChecking = true;
133
+ this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
134
+ // Send message to worker
135
+ this.worker.postMessage("checkDevTools");
136
+ // Set timeout for missing second heartbeat
137
+ this.timeoutId = window.setTimeout(() => {
138
+ // If we reach here, the worker is paused at debugger
139
+ // which means DevTools is open
140
+ this.isChecking = false;
141
+ this.updateDevToolsState(true);
142
+ }, this.timeoutDuration);
143
+ });
144
+ }
145
+ /**
146
+ * Terminate the worker and clean up resources
147
+ */
148
+ terminateWorker() {
149
+ this.safeExecute("terminateWorker", DetectorErrorType.DISPOSAL_ERROR, () => {
150
+ if (this.worker) {
151
+ this.worker.terminate();
152
+ this.worker = null;
153
+ }
154
+ });
155
+ }
156
+ /**
157
+ * Clean up resources
158
+ */
159
+ dispose() {
160
+ this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
161
+ if (this.timeoutId !== null) {
162
+ clearTimeout(this.timeoutId);
163
+ this.timeoutId = null;
164
+ }
165
+ this.terminateWorker();
166
+ this.isInitialized = false;
167
+ this.logger.log("Disposed");
168
+ });
169
+ super.dispose();
170
+ }
171
+ /**
172
+ * Check if this detector is supported in the current browser
173
+ * @returns True if supported
174
+ */
175
+ static isSupported() {
176
+ if (!isBrowser())
177
+ return false;
178
+ // Check if Web Workers are supported
179
+ if (typeof Worker === "undefined") {
180
+ return false;
181
+ }
182
+ // Check if Blob URLs are supported (needed for creating worker scripts)
183
+ if (typeof Blob === "undefined" || typeof URL === "undefined" || typeof URL.createObjectURL !== "function") {
184
+ return false;
185
+ }
186
+ // Check if we can create a worker from a blob URL
187
+ // Some environments restrict this for security reasons
188
+ try {
189
+ const blob = new Blob([""], { type: "application/javascript" });
190
+ const url = URL.createObjectURL(blob);
191
+ const worker = new Worker(url);
192
+ worker.terminate();
193
+ URL.revokeObjectURL(url);
194
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
195
+ }
196
+ catch (error) {
197
+ // If we can't create a worker, this detector won't work
198
+ return false;
199
+ }
200
+ // Get browser info
201
+ const browser = getBrowser();
202
+ const isMobileDevice = isMobile();
203
+ // This detector works best in Chromium-based browsers
204
+ // It's generally reliable across most desktop browsers
205
+ // Some older iOS browsers have issues with the debugger statement
206
+ if (isMobileDevice && browser.name === "safari" && Number.parseInt(browser.version, 10) < 14) {
207
+ return false;
208
+ }
209
+ return true;
210
+ }
211
+ }
@@ -0,0 +1,48 @@
1
+ import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
2
+ import { DevToolsDetectorOptions } from "./detectorInterface";
3
+ /**
4
+ * Options for the DefineGetterDetector
5
+ */
6
+ export interface DefineGetterDetectorOptions extends DevToolsDetectorOptions {
7
+ /**
8
+ * Check interval in milliseconds
9
+ */
10
+ checkInterval?: number;
11
+ }
12
+ /**
13
+ * Detector that uses property getter access to detect DevTools
14
+ * This works by creating an element with a getter that triggers when DevTools inspects it
15
+ */
16
+ export declare class DefineGetterDetector extends AbstractDevToolsDetector {
17
+ private checkInterval;
18
+ private div;
19
+ private detectionCount;
20
+ private lastDetectionTime;
21
+ /**
22
+ * Create a new DefineGetterDetector
23
+ * @param options Configuration options
24
+ */
25
+ constructor(options?: DefineGetterDetectorOptions);
26
+ /**
27
+ * Initialize the div element with custom getter for detection
28
+ */
29
+ private initDetectionElement;
30
+ /**
31
+ * Handle getter access - called when the 'id' property is accessed
32
+ */
33
+ private handleGetterAccess;
34
+ /**
35
+ * Check if DevTools is open by logging the div element
36
+ * When the element is logged, DevTools will access its properties including 'id'
37
+ */
38
+ checkDevTools(): void;
39
+ /**
40
+ * Clean up resources
41
+ */
42
+ dispose(): void;
43
+ /**
44
+ * Check if this detector is supported in the current browser
45
+ * @returns True if supported
46
+ */
47
+ static isSupported(): boolean;
48
+ }
@@ -0,0 +1,150 @@
1
+ import { isBrowser } from "../environment";
2
+ import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
3
+ /**
4
+ * Detector that uses property getter access to detect DevTools
5
+ * This works by creating an element with a getter that triggers when DevTools inspects it
6
+ */
7
+ export class DefineGetterDetector extends AbstractDevToolsDetector {
8
+ /**
9
+ * Create a new DefineGetterDetector
10
+ * @param options Configuration options
11
+ */
12
+ constructor(options = {}) {
13
+ super("DefineGetterDetector", options);
14
+ this.div = null;
15
+ this.detectionCount = 0;
16
+ this.lastDetectionTime = 0;
17
+ this.checkInterval = options.checkInterval || 1000;
18
+ // Initialize the div element with custom getter
19
+ this.initDetectionElement();
20
+ this.logger.log("Initialized with interval:", this.checkInterval);
21
+ }
22
+ /**
23
+ * Initialize the div element with custom getter for detection
24
+ */
25
+ initDetectionElement() {
26
+ this.safeExecute("initDetectionElement", DetectorErrorType.INITIALIZATION_ERROR, () => {
27
+ if (!isBrowser())
28
+ return;
29
+ this.div = document.createElement("div");
30
+ // Define a getter for the 'id' property that will be triggered when DevTools inspects the element
31
+ // Using both __defineGetter__ (for older browsers) and Object.defineProperty
32
+ try {
33
+ // This is a non-standard method but works in some browsers
34
+ ;
35
+ this.div.__defineGetter__("id", () => {
36
+ this.handleGetterAccess();
37
+ return "";
38
+ });
39
+ }
40
+ catch (e) {
41
+ // Ignore errors for browsers that don't support __defineGetter__
42
+ this.logger.log("__defineGetter__ not supported, using Object.defineProperty", e);
43
+ }
44
+ // Standard way using Object.defineProperty
45
+ Object.defineProperty(this.div, "id", {
46
+ get: () => {
47
+ this.handleGetterAccess();
48
+ return "";
49
+ },
50
+ configurable: true,
51
+ });
52
+ this.logger.log("Detection element initialized");
53
+ });
54
+ }
55
+ /**
56
+ * Handle getter access - called when the 'id' property is accessed
57
+ */
58
+ handleGetterAccess() {
59
+ this.safeExecute("handleGetterAccess", DetectorErrorType.DETECTION_ERROR, () => {
60
+ const now = Date.now();
61
+ this.detectionCount++;
62
+ // Avoid triggering too many times in a short period
63
+ if (now - this.lastDetectionTime < 100) {
64
+ this.detectionCount++;
65
+ }
66
+ else {
67
+ this.detectionCount = 1;
68
+ }
69
+ this.lastDetectionTime = now;
70
+ // If the getter is accessed multiple times in a short period, DevTools is likely open
71
+ if (this.detectionCount >= 2 && !this.isDevToolsOpen) {
72
+ this.updateDevToolsState(true);
73
+ this.logger.log("DevTools opened (getter accessed multiple times)");
74
+ }
75
+ });
76
+ }
77
+ /**
78
+ * Check if DevTools is open by logging the div element
79
+ * When the element is logged, DevTools will access its properties including 'id'
80
+ */
81
+ checkDevTools() {
82
+ if (this.isChecking || !isBrowser() || !this.div)
83
+ return;
84
+ this.isChecking = true;
85
+ this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
86
+ // Log the div element - this will trigger property access in DevTools
87
+ console.log(this.div);
88
+ // Clear console to avoid clutter
89
+ if (!this.debugMode) {
90
+ console.clear();
91
+ }
92
+ // If no detection occurred within a short time after logging,
93
+ // DevTools is likely closed
94
+ setTimeout(() => {
95
+ this.safeExecute("checkDevToolsTimeout", DetectorErrorType.DETECTION_ERROR, () => {
96
+ const now = Date.now();
97
+ if (now - this.lastDetectionTime > 500 && this.isDevToolsOpen) {
98
+ this.updateDevToolsState(false);
99
+ this.logger.log("DevTools closed (no recent getter access)");
100
+ }
101
+ this.isChecking = false;
102
+ });
103
+ }, 100);
104
+ });
105
+ // Ensure isChecking is reset if an error occurs
106
+ if (this.isChecking) {
107
+ setTimeout(() => {
108
+ this.isChecking = false;
109
+ }, 200);
110
+ }
111
+ }
112
+ /**
113
+ * Clean up resources
114
+ */
115
+ dispose() {
116
+ this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
117
+ this.div = null;
118
+ this.logger.log("Disposed");
119
+ });
120
+ super.dispose();
121
+ }
122
+ /**
123
+ * Check if this detector is supported in the current browser
124
+ * @returns True if supported
125
+ */
126
+ static isSupported() {
127
+ if (!isBrowser())
128
+ return false;
129
+ try {
130
+ // Test if we can define getters on an element
131
+ const testDiv = document.createElement("div");
132
+ let testValue = false;
133
+ Object.defineProperty(testDiv, "testProp", {
134
+ get: () => {
135
+ testValue = true;
136
+ return "";
137
+ },
138
+ configurable: true,
139
+ });
140
+ // Access the property to see if the getter works
141
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
142
+ const value = testDiv.testProp;
143
+ return testValue;
144
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
145
+ }
146
+ catch (e) {
147
+ return false;
148
+ }
149
+ }
150
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Interface for all DevTools detector implementations
3
+ */
4
+ export interface DevToolsDetector {
5
+ /**
6
+ * Check if DevTools is currently open
7
+ */
8
+ checkDevTools(): void;
9
+ /**
10
+ * Get the current DevTools state
11
+ * @returns True if DevTools is open
12
+ */
13
+ isOpen(): boolean;
14
+ /**
15
+ * Clean up resources
16
+ */
17
+ dispose(): void;
18
+ /**
19
+ * Set debug mode
20
+ * @param enabled Whether debug mode should be enabled
21
+ */
22
+ setDebugMode(enabled: boolean): void;
23
+ }
24
+ /**
25
+ * Common options for all DevTools detectors
26
+ */
27
+ export interface DevToolsDetectorOptions {
28
+ /**
29
+ * Callback function when DevTools state changes
30
+ */
31
+ onDevToolsChange?: (isOpen: boolean) => void;
32
+ /**
33
+ * Enable debug mode for troubleshooting
34
+ */
35
+ debugMode?: boolean;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import type { DevToolsDetectorOptions } from "./detectorInterface";
2
+ import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
3
+ /**
4
+ * Type for detector types
5
+ */
6
+ export type DetectorType = "debugger" | "timing" | "dateToString" | "funcToString" | "regToString" | "defineGetter" | "debugLib" | "size";
7
+ /**
8
+ * Options for the DevTools detector manager
9
+ */
10
+ export interface DetectorManagerOptions extends DevToolsDetectorOptions {
11
+ /**
12
+ * Enable specific detection methods
13
+ */
14
+ enabledDetectors?: DetectorType[];
15
+ /**
16
+ * Timeout duration for the debugger detector
17
+ */
18
+ debuggerTimeoutDuration?: number;
19
+ /**
20
+ * Check interval in milliseconds
21
+ */
22
+ checkInterval?: number;
23
+ /**
24
+ * Delay initial check to avoid false positives during page load
25
+ * @default true
26
+ */
27
+ delayInitialCheck?: boolean;
28
+ /**
29
+ * Initial check delay in milliseconds
30
+ * @default 1000
31
+ */
32
+ initialCheckDelay?: number;
33
+ }
34
+ /**
35
+ * Manager class that coordinates multiple DevTools detection methods
36
+ * **Chrome, Edge, Opera**: Primarily uses `DebuggerDetector` with `DefineGetterDetector` as backup
37
+ * **Firefox**: Uses `TimingDetector` and `RegToStringDetector` for reliable detection
38
+ * **Safari**: Primarily uses `DateToStringDetector` with `DefineGetterDetector` as backup
39
+ * **QQ Browser**: Uses `RegToStringDetector` which works particularly well for this browser
40
+ * **Mobile Browsers**: Always includes `DebugLibDetector` to catch third-party debugging tools
41
+ */
42
+ export declare class DevToolsDetectorManager extends AbstractDevToolsDetector {
43
+ private detectors;
44
+ private activeDetectors;
45
+ private browserInfo;
46
+ private isMobileDevice;
47
+ private isInitialCheckDone;
48
+ private initialCheckTimeout;
49
+ private delayInitialCheck;
50
+ private initialCheckDelay;
51
+ private static readonly BROWSER_DETECTOR_MAP;
52
+ private static readonly MOBILE_DETECTOR_MAP;
53
+ /**
54
+ * Create a new DevToolsDetectorManager
55
+ * @param options Configuration options
56
+ */
57
+ constructor(options?: DetectorManagerOptions);
58
+ /**
59
+ * Initialize all available detectors
60
+ */
61
+ private initializeAllDetectors;
62
+ /**
63
+ * Select which detectors to activate based on browser
64
+ */
65
+ private selectActiveDetectors;
66
+ /**
67
+ * Handle state change from any detector
68
+ */
69
+ private handleDetectorChange;
70
+ /**
71
+ * Check if DevTools is open using all active detectors
72
+ */
73
+ checkDevTools(): void;
74
+ /**
75
+ * Get the current DevTools state
76
+ * @returns True if DevTools is open
77
+ */
78
+ isOpen(): boolean;
79
+ /**
80
+ * Clean up resources for all detectors
81
+ */
82
+ dispose(): void;
83
+ /**
84
+ * Set debug mode for all detectors
85
+ * @param enabled Whether debug mode should be enabled
86
+ */
87
+ setDebugMode(enabled: boolean): void;
88
+ }