@tindalabs/shield 0.1.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.
- package/LICENSE +9 -0
- package/README.md +357 -0
- package/dist/assess.d.ts +16 -0
- package/dist/assess.js +220 -0
- package/dist/config/default-extensions-config.json +103 -0
- package/dist/core/ContentProtector.d.ts +63 -0
- package/dist/core/ContentProtector.js +281 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/mediator/ContentProtectionMediator.d.ts +86 -0
- package/dist/core/mediator/ContentProtectionMediator.js +238 -0
- package/dist/core/mediator/eventDataTypes.d.ts +112 -0
- package/dist/core/mediator/eventDataTypes.js +23 -0
- package/dist/core/mediator/handlers/abstractEventHandler.d.ts +41 -0
- package/dist/core/mediator/handlers/abstractEventHandler.js +59 -0
- package/dist/core/mediator/handlers/devToolsEventHandler.d.ts +9 -0
- package/dist/core/mediator/handlers/devToolsEventHandler.js +95 -0
- package/dist/core/mediator/handlers/eventHandlerRegistry.d.ts +9 -0
- package/dist/core/mediator/handlers/eventHandlerRegistry.js +34 -0
- package/dist/core/mediator/handlers/extensionEventHandlers.d.ts +40 -0
- package/dist/core/mediator/handlers/extensionEventHandlers.js +140 -0
- package/dist/core/mediator/handlers/iFrameEventHandlers.d.ts +27 -0
- package/dist/core/mediator/handlers/iFrameEventHandlers.js +93 -0
- package/dist/core/mediator/handlers/screenShotEventHandlers.d.ts +34 -0
- package/dist/core/mediator/handlers/screenShotEventHandlers.js +111 -0
- package/dist/core/mediator/protection-event.d.ts +77 -0
- package/dist/core/mediator/protection-event.js +32 -0
- package/dist/core/mediator/types.d.ts +105 -0
- package/dist/core/mediator/types.js +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +7 -0
- package/dist/otel.d.ts +24 -0
- package/dist/otel.js +83 -0
- package/dist/policy.d.ts +98 -0
- package/dist/policy.js +97 -0
- package/dist/strategies/AbstractStrategy.d.ts +124 -0
- package/dist/strategies/AbstractStrategy.js +256 -0
- package/dist/strategies/ClipboardStrategy.d.ts +67 -0
- package/dist/strategies/ClipboardStrategy.js +291 -0
- package/dist/strategies/ContextMenuStrategy.d.ts +60 -0
- package/dist/strategies/ContextMenuStrategy.js +454 -0
- package/dist/strategies/DevToolsStrategy.d.ts +55 -0
- package/dist/strategies/DevToolsStrategy.js +314 -0
- package/dist/strategies/ExtensionStrategy.d.ts +66 -0
- package/dist/strategies/ExtensionStrategy.js +486 -0
- package/dist/strategies/IFrameStrategy.d.ts +49 -0
- package/dist/strategies/IFrameStrategy.js +255 -0
- package/dist/strategies/KeyboardStrategy.d.ts +35 -0
- package/dist/strategies/KeyboardStrategy.js +130 -0
- package/dist/strategies/PrintStrategy.d.ts +47 -0
- package/dist/strategies/PrintStrategy.js +201 -0
- package/dist/strategies/ScreenshotStrategy.d.ts +90 -0
- package/dist/strategies/ScreenshotStrategy.js +502 -0
- package/dist/strategies/SelectionStrategy.d.ts +49 -0
- package/dist/strategies/SelectionStrategy.js +216 -0
- package/dist/strategies/WatermarkStrategy.d.ts +56 -0
- package/dist/strategies/WatermarkStrategy.js +287 -0
- package/dist/strategies/index.d.ts +10 -0
- package/dist/strategies/index.js +11 -0
- package/dist/types/assessment.d.ts +62 -0
- package/dist/types/assessment.js +1 -0
- package/dist/types/index.d.ts +278 -0
- package/dist/types/index.js +17 -0
- package/dist/utils/DOMObserver.d.ts +68 -0
- package/dist/utils/DOMObserver.js +134 -0
- package/dist/utils/base/LoggableComponent.d.ts +44 -0
- package/dist/utils/base/LoggableComponent.js +56 -0
- package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +98 -0
- package/dist/utils/detectors/AbstractDevToolsDetector.js +127 -0
- package/dist/utils/detectors/dateToStringDetector.d.ts +43 -0
- package/dist/utils/detectors/dateToStringDetector.js +96 -0
- package/dist/utils/detectors/debugLibDetector.d.ts +64 -0
- package/dist/utils/detectors/debugLibDetector.js +195 -0
- package/dist/utils/detectors/debuggerDetector.d.ts +51 -0
- package/dist/utils/detectors/debuggerDetector.js +211 -0
- package/dist/utils/detectors/defineGetterDetector.d.ts +48 -0
- package/dist/utils/detectors/defineGetterDetector.js +150 -0
- package/dist/utils/detectors/detectorInterface.d.ts +36 -0
- package/dist/utils/detectors/detectorInterface.js +1 -0
- package/dist/utils/detectors/devToolsDetectorManager.d.ts +88 -0
- package/dist/utils/detectors/devToolsDetectorManager.js +243 -0
- package/dist/utils/detectors/funcToStringDetector.d.ts +43 -0
- package/dist/utils/detectors/funcToStringDetector.js +90 -0
- package/dist/utils/detectors/regToStringDetector.d.ts +43 -0
- package/dist/utils/detectors/regToStringDetector.js +129 -0
- package/dist/utils/detectors/sizeDetector.d.ts +54 -0
- package/dist/utils/detectors/sizeDetector.js +134 -0
- package/dist/utils/detectors/timingDetector.d.ts +55 -0
- package/dist/utils/detectors/timingDetector.js +143 -0
- package/dist/utils/dom.d.ts +20 -0
- package/dist/utils/dom.js +83 -0
- package/dist/utils/environment.d.ts +29 -0
- package/dist/utils/environment.js +267 -0
- package/dist/utils/eventManager.d.ts +162 -0
- package/dist/utils/eventManager.js +548 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/intervalManager.d.ts +91 -0
- package/dist/utils/intervalManager.js +221 -0
- package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.d.ts +41 -0
- package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.js +135 -0
- package/dist/utils/keyboardShortcutManager/keyboardShortcuts.d.ts +18 -0
- package/dist/utils/keyboardShortcutManager/keyboardShortcuts.js +195 -0
- package/dist/utils/logging/simple/Loggable.d.ts +33 -0
- package/dist/utils/logging/simple/Loggable.js +1 -0
- package/dist/utils/logging/simple/LoggingDelegate.d.ts +42 -0
- package/dist/utils/logging/simple/LoggingDelegate.js +53 -0
- package/dist/utils/logging/simple/SimpleLoggingService.d.ts +39 -0
- package/dist/utils/logging/simple/SimpleLoggingService.js +58 -0
- package/dist/utils/orientation.d.ts +15 -0
- package/dist/utils/orientation.js +32 -0
- package/dist/utils/protectedContentManager.d.ts +155 -0
- package/dist/utils/protectedContentManager.js +424 -0
- package/dist/utils/securityOverlayManager.d.ts +253 -0
- package/dist/utils/securityOverlayManager.js +786 -0
- package/dist/utils/timeoutManager.d.ts +50 -0
- package/dist/utils/timeoutManager.js +113 -0
- package/package.json +61 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { LoggableComponent } from "../base/LoggableComponent";
|
|
2
|
+
/**
|
|
3
|
+
* Enum representing different types of errors that can occur in detectors
|
|
4
|
+
*/
|
|
5
|
+
export var DetectorErrorType;
|
|
6
|
+
(function (DetectorErrorType) {
|
|
7
|
+
/**
|
|
8
|
+
* Error during initialization of a detector
|
|
9
|
+
*/
|
|
10
|
+
DetectorErrorType["INITIALIZATION_ERROR"] = "initialization_error";
|
|
11
|
+
/**
|
|
12
|
+
* Error during detection check
|
|
13
|
+
*/
|
|
14
|
+
DetectorErrorType["DETECTION_ERROR"] = "detection_error";
|
|
15
|
+
/**
|
|
16
|
+
* Error related to browser compatibility
|
|
17
|
+
*/
|
|
18
|
+
DetectorErrorType["COMPATIBILITY_ERROR"] = "compatibility_error";
|
|
19
|
+
/**
|
|
20
|
+
* Error during cleanup/disposal
|
|
21
|
+
*/
|
|
22
|
+
DetectorErrorType["DISPOSAL_ERROR"] = "disposal_error";
|
|
23
|
+
/**
|
|
24
|
+
* Error in worker communication
|
|
25
|
+
*/
|
|
26
|
+
DetectorErrorType["WORKER_ERROR"] = "worker_error";
|
|
27
|
+
/**
|
|
28
|
+
* Error in DOM manipulation
|
|
29
|
+
*/
|
|
30
|
+
DetectorErrorType["DOM_ERROR"] = "dom_error";
|
|
31
|
+
/**
|
|
32
|
+
* Error in event handling
|
|
33
|
+
*/
|
|
34
|
+
DetectorErrorType["EVENT_ERROR"] = "event_error";
|
|
35
|
+
/**
|
|
36
|
+
* Unexpected or unknown error
|
|
37
|
+
*/
|
|
38
|
+
DetectorErrorType["UNKNOWN_ERROR"] = "unknown_error";
|
|
39
|
+
})(DetectorErrorType || (DetectorErrorType = {}));
|
|
40
|
+
/**
|
|
41
|
+
* Abstract base class for DevTools detectors
|
|
42
|
+
* Implements common functionality to reduce duplication across detector implementations
|
|
43
|
+
*/
|
|
44
|
+
export class AbstractDevToolsDetector extends LoggableComponent {
|
|
45
|
+
/**
|
|
46
|
+
* Create a new detector instance
|
|
47
|
+
* @param detectorName Name of the detector for logging
|
|
48
|
+
* @param options Configuration options
|
|
49
|
+
*/
|
|
50
|
+
constructor(detectorName, options = {}) {
|
|
51
|
+
super(detectorName, !!options.debugMode);
|
|
52
|
+
this.detectorName = detectorName;
|
|
53
|
+
this.isDevToolsOpen = false;
|
|
54
|
+
this.isChecking = false;
|
|
55
|
+
this.onDevToolsChange = options.onDevToolsChange || (() => { });
|
|
56
|
+
this.logger.log("Initialized");
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the current DevTools state
|
|
60
|
+
* @returns True if DevTools is open
|
|
61
|
+
*/
|
|
62
|
+
isOpen() {
|
|
63
|
+
return this.isDevToolsOpen;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Update the DevTools state and notify listeners if changed
|
|
67
|
+
* @param isOpen New DevTools state
|
|
68
|
+
*/
|
|
69
|
+
updateDevToolsState(isOpen) {
|
|
70
|
+
// Only trigger callback if state changed
|
|
71
|
+
if (isOpen !== this.isDevToolsOpen) {
|
|
72
|
+
this.isDevToolsOpen = isOpen;
|
|
73
|
+
this.onDevToolsChange(isOpen);
|
|
74
|
+
this.logger.log(`DevTools ${isOpen ? "opened" : "closed"}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Handle an error with appropriate logging
|
|
79
|
+
* @param errorType Type of error that occurred
|
|
80
|
+
* @param message Error message
|
|
81
|
+
* @param error The error object
|
|
82
|
+
*/
|
|
83
|
+
handleError(errorType, message, error) {
|
|
84
|
+
this.logger.error(`[${errorType}] ${message}:`, error);
|
|
85
|
+
// Additional error handling logic can be added here
|
|
86
|
+
// For example, reporting errors to a monitoring service
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Execute a function with error handling
|
|
90
|
+
* @param operation Name of the operation for error reporting
|
|
91
|
+
* @param errorType Type of error to report if the operation fails
|
|
92
|
+
* @param fn Function to execute
|
|
93
|
+
* @returns The result of the function or undefined if an error occurred
|
|
94
|
+
*/
|
|
95
|
+
safeExecute(operation, errorType, fn) {
|
|
96
|
+
try {
|
|
97
|
+
return fn();
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.handleError(errorType, `Error during ${operation}`, error);
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Execute an async function with error handling
|
|
106
|
+
* @param operation Name of the operation for error reporting
|
|
107
|
+
* @param errorType Type of error to report if the operation fails
|
|
108
|
+
* @param fn Async function to execute
|
|
109
|
+
* @returns Promise resolving to the result of the function or undefined if an error occurred
|
|
110
|
+
*/
|
|
111
|
+
async safeExecuteAsync(operation, errorType, fn) {
|
|
112
|
+
try {
|
|
113
|
+
return await fn();
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
this.handleError(errorType, `Error during ${operation}`, error);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Clean up resources
|
|
122
|
+
* Override in subclasses to perform detector-specific cleanup
|
|
123
|
+
*/
|
|
124
|
+
dispose() {
|
|
125
|
+
this.logger.log("Disposed");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
|
|
2
|
+
import { DevToolsDetectorOptions } from "./detectorInterface";
|
|
3
|
+
/**
|
|
4
|
+
* Options for the DateToStringDetector
|
|
5
|
+
*/
|
|
6
|
+
export interface DateToStringDetectorOptions extends DevToolsDetectorOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Threshold for detection (number of toString calls)
|
|
9
|
+
*/
|
|
10
|
+
threshold?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Utility class for detecting DevTools using Date.toString behavior
|
|
14
|
+
* This approach works by detecting multiple calls to toString when an object is logged
|
|
15
|
+
* and DevTools is open
|
|
16
|
+
*/
|
|
17
|
+
export declare class DateToStringDetector extends AbstractDevToolsDetector {
|
|
18
|
+
private date;
|
|
19
|
+
private count;
|
|
20
|
+
private threshold;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new DateToStringDetector
|
|
23
|
+
* @param options Configuration options
|
|
24
|
+
*/
|
|
25
|
+
constructor(options?: DateToStringDetectorOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Initialize the date object with custom toString method
|
|
28
|
+
*/
|
|
29
|
+
private initDateObject;
|
|
30
|
+
/**
|
|
31
|
+
* Check if DevTools is open using Date.toString behavior
|
|
32
|
+
*/
|
|
33
|
+
checkDevTools(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Clean up resources
|
|
36
|
+
*/
|
|
37
|
+
dispose(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Check if this detector is supported in the current browser
|
|
40
|
+
* @returns True if supported
|
|
41
|
+
*/
|
|
42
|
+
static isSupported(): boolean;
|
|
43
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { isBrowser, getBrowser, isMobile } from "../environment";
|
|
2
|
+
import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
|
|
3
|
+
/**
|
|
4
|
+
* Utility class for detecting DevTools using Date.toString behavior
|
|
5
|
+
* This approach works by detecting multiple calls to toString when an object is logged
|
|
6
|
+
* and DevTools is open
|
|
7
|
+
*/
|
|
8
|
+
export class DateToStringDetector extends AbstractDevToolsDetector {
|
|
9
|
+
/**
|
|
10
|
+
* Create a new DateToStringDetector
|
|
11
|
+
* @param options Configuration options
|
|
12
|
+
*/
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
super("DateToStringDetector", options);
|
|
15
|
+
this.date = null;
|
|
16
|
+
this.count = 0;
|
|
17
|
+
this.debugMode = !!options.debugMode;
|
|
18
|
+
this.onDevToolsChange = options.onDevToolsChange || (() => { });
|
|
19
|
+
this.threshold = options.threshold || 2;
|
|
20
|
+
// Initialize the date object with custom toString
|
|
21
|
+
this.initDateObject();
|
|
22
|
+
this.logger.log("Initialized with threshold:", this.threshold);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Initialize the date object with custom toString method
|
|
26
|
+
*/
|
|
27
|
+
initDateObject() {
|
|
28
|
+
this.safeExecute("initDateObject", DetectorErrorType.INITIALIZATION_ERROR, () => {
|
|
29
|
+
if (!isBrowser())
|
|
30
|
+
return;
|
|
31
|
+
this.date = new Date();
|
|
32
|
+
// Override toString to count calls
|
|
33
|
+
this.date.toString = () => {
|
|
34
|
+
this.count++;
|
|
35
|
+
// Use a hidden property to avoid infinite recursion when logging
|
|
36
|
+
const originalDate = this.date ? new Date(this.date.getTime()) : new Date();
|
|
37
|
+
this.logger.log(`toString() called (${this.count} times)`, originalDate.toISOString());
|
|
38
|
+
return "";
|
|
39
|
+
};
|
|
40
|
+
this.logger.log("Date object initialized");
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if DevTools is open using Date.toString behavior
|
|
45
|
+
*/
|
|
46
|
+
checkDevTools() {
|
|
47
|
+
if (this.isChecking || !isBrowser())
|
|
48
|
+
return;
|
|
49
|
+
this.isChecking = true;
|
|
50
|
+
this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
|
|
51
|
+
// Reset counter
|
|
52
|
+
this.count = 0;
|
|
53
|
+
// Log the date object - this will trigger toString
|
|
54
|
+
console.log(this.date);
|
|
55
|
+
// Clear console to avoid clutter
|
|
56
|
+
if (!this.debugMode) {
|
|
57
|
+
console.clear();
|
|
58
|
+
}
|
|
59
|
+
// If toString was called multiple times, DevTools is likely open
|
|
60
|
+
const isOpen = this.count >= this.threshold;
|
|
61
|
+
// Update state and notify listeners if changed
|
|
62
|
+
this.updateDevToolsState(isOpen);
|
|
63
|
+
this.logger.log(`toString called ${this.count} times, threshold: ${this.threshold}`);
|
|
64
|
+
this.isChecking = false;
|
|
65
|
+
});
|
|
66
|
+
// Ensure isChecking is reset even if an error occurs
|
|
67
|
+
if (this.isChecking) {
|
|
68
|
+
this.isChecking = false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Clean up resources
|
|
73
|
+
*/
|
|
74
|
+
dispose() {
|
|
75
|
+
this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
|
|
76
|
+
this.date = null;
|
|
77
|
+
this.logger.log("Disposed");
|
|
78
|
+
});
|
|
79
|
+
super.dispose();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if this detector is supported in the current browser
|
|
83
|
+
* @returns True if supported
|
|
84
|
+
*/
|
|
85
|
+
static isSupported() {
|
|
86
|
+
if (!isBrowser())
|
|
87
|
+
return false;
|
|
88
|
+
const browser = getBrowser();
|
|
89
|
+
const isMobileDevice = isMobile();
|
|
90
|
+
// Not supported in iOS Chrome or iOS Edge
|
|
91
|
+
if (isMobileDevice && (browser.name === "chrome" || browser.name === "edge")) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
|
|
2
|
+
import { DevToolsDetectorOptions } from "./detectorInterface";
|
|
3
|
+
/**
|
|
4
|
+
* Options for the DebugLibDetector
|
|
5
|
+
*/
|
|
6
|
+
export interface DebugLibDetectorOptions extends DevToolsDetectorOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Check interval in milliseconds
|
|
9
|
+
*/
|
|
10
|
+
checkInterval?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Additional libraries to check for beyond the default ones
|
|
13
|
+
* Format: { name: string, globalVar: string }
|
|
14
|
+
*/
|
|
15
|
+
additionalLibraries?: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
globalVar: string;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Detector that checks for third-party debugging libraries like Eruda and vConsole
|
|
22
|
+
*/
|
|
23
|
+
export declare class DebugLibDetector extends AbstractDevToolsDetector {
|
|
24
|
+
private checkInterval;
|
|
25
|
+
private taskId;
|
|
26
|
+
private libraries;
|
|
27
|
+
private static readonly DEFAULT_LIBRARIES;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new DebugLibDetector
|
|
30
|
+
* @param options Configuration options
|
|
31
|
+
*/
|
|
32
|
+
constructor(options?: DebugLibDetectorOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Start continuous detection
|
|
35
|
+
*/
|
|
36
|
+
startDetection(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Stop continuous detection
|
|
39
|
+
*/
|
|
40
|
+
stopDetection(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Check if any debug libraries are present in the global scope
|
|
43
|
+
*/
|
|
44
|
+
checkDevTools(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Detect which debug libraries are present
|
|
47
|
+
* @returns Array of detected library names
|
|
48
|
+
*/
|
|
49
|
+
private detectDebugLibraries;
|
|
50
|
+
/**
|
|
51
|
+
* Clean up resources
|
|
52
|
+
*/
|
|
53
|
+
dispose(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Static utility to check if any debug libraries are present
|
|
56
|
+
* @returns True if any debug library is detected
|
|
57
|
+
*/
|
|
58
|
+
static isAnyDebugLibPresent(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Check if this detector is supported in the current browser
|
|
61
|
+
* @returns True if supported
|
|
62
|
+
*/
|
|
63
|
+
static isSupported(): boolean;
|
|
64
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { isBrowser } from "../environment";
|
|
2
|
+
import { intervalManager } from "../intervalManager";
|
|
3
|
+
import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
|
|
4
|
+
/**
|
|
5
|
+
* Detector that checks for third-party debugging libraries like Eruda and vConsole
|
|
6
|
+
*/
|
|
7
|
+
export class DebugLibDetector extends AbstractDevToolsDetector {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new DebugLibDetector
|
|
10
|
+
* @param options Configuration options
|
|
11
|
+
*/
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
super("DebugLibDetector", options);
|
|
14
|
+
this.taskId = null;
|
|
15
|
+
this.checkInterval = options.checkInterval || 1000;
|
|
16
|
+
// Combine default libraries with any additional ones
|
|
17
|
+
this.libraries = [...DebugLibDetector.DEFAULT_LIBRARIES];
|
|
18
|
+
if (options.additionalLibraries && Array.isArray(options.additionalLibraries)) {
|
|
19
|
+
this.libraries = [...this.libraries, ...options.additionalLibraries];
|
|
20
|
+
}
|
|
21
|
+
this.logger.log("Initialized with interval:", this.checkInterval);
|
|
22
|
+
this.logger.log("Monitoring libraries:", this.libraries.map((lib) => lib.name).join(", "));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start continuous detection
|
|
26
|
+
*/
|
|
27
|
+
startDetection() {
|
|
28
|
+
return this.safeExecute("startDetection", DetectorErrorType.INITIALIZATION_ERROR, () => {
|
|
29
|
+
if (this.taskId || !isBrowser())
|
|
30
|
+
return;
|
|
31
|
+
// Register with IntervalManager for periodic checks
|
|
32
|
+
this.taskId = intervalManager.registerTask("debug-lib-detection", () => {
|
|
33
|
+
this.checkDevTools();
|
|
34
|
+
}, this.checkInterval);
|
|
35
|
+
this.logger.log(`Started continuous detection with task ID ${this.taskId}`);
|
|
36
|
+
// Perform initial check
|
|
37
|
+
this.checkDevTools();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Stop continuous detection
|
|
42
|
+
*/
|
|
43
|
+
stopDetection() {
|
|
44
|
+
return this.safeExecute("stopDetection", DetectorErrorType.DISPOSAL_ERROR, () => {
|
|
45
|
+
if (!this.taskId)
|
|
46
|
+
return;
|
|
47
|
+
// Unregister from IntervalManager
|
|
48
|
+
intervalManager.unregisterTask(this.taskId);
|
|
49
|
+
this.taskId = null;
|
|
50
|
+
this.logger.log("Stopped continuous detection");
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if any debug libraries are present in the global scope
|
|
55
|
+
*/
|
|
56
|
+
checkDevTools() {
|
|
57
|
+
if (this.isChecking || !isBrowser())
|
|
58
|
+
return;
|
|
59
|
+
this.isChecking = true;
|
|
60
|
+
this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
|
|
61
|
+
// Check for any debug libraries
|
|
62
|
+
const detectedLibraries = this.detectDebugLibraries();
|
|
63
|
+
const isOpen = detectedLibraries.length > 0;
|
|
64
|
+
if (isOpen) {
|
|
65
|
+
this.logger.log(`Debug libraries detected: ${detectedLibraries.join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.logger.log("No debug libraries detected");
|
|
69
|
+
}
|
|
70
|
+
// Update state and notify listeners if changed
|
|
71
|
+
this.updateDevToolsState(isOpen);
|
|
72
|
+
this.isChecking = false;
|
|
73
|
+
});
|
|
74
|
+
// Ensure isChecking is reset even if an error occurs
|
|
75
|
+
if (this.isChecking) {
|
|
76
|
+
this.isChecking = false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect which debug libraries are present
|
|
81
|
+
* @returns Array of detected library names
|
|
82
|
+
*/
|
|
83
|
+
detectDebugLibraries() {
|
|
84
|
+
return (this.safeExecute("detectDebugLibraries", DetectorErrorType.DETECTION_ERROR, () => {
|
|
85
|
+
const detected = [];
|
|
86
|
+
for (const lib of this.libraries) {
|
|
87
|
+
try {
|
|
88
|
+
// Check if the global variable exists
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
+
if (typeof window[lib.globalVar] !== "undefined") {
|
|
91
|
+
detected.push(lib.name);
|
|
92
|
+
}
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
// Ignore errors in property access
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return detected;
|
|
100
|
+
}) || []);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Clean up resources
|
|
104
|
+
*/
|
|
105
|
+
dispose() {
|
|
106
|
+
this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
|
|
107
|
+
this.stopDetection();
|
|
108
|
+
this.logger.log("Disposed");
|
|
109
|
+
});
|
|
110
|
+
super.dispose();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Static utility to check if any debug libraries are present
|
|
114
|
+
* @returns True if any debug library is detected
|
|
115
|
+
*/
|
|
116
|
+
static isAnyDebugLibPresent() {
|
|
117
|
+
if (!isBrowser())
|
|
118
|
+
return false;
|
|
119
|
+
try {
|
|
120
|
+
for (const lib of DebugLibDetector.DEFAULT_LIBRARIES) {
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
if (typeof window[lib.globalVar] !== "undefined") {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if this detector is supported in the current browser
|
|
135
|
+
* @returns True if supported
|
|
136
|
+
*/
|
|
137
|
+
static isSupported() {
|
|
138
|
+
if (!isBrowser())
|
|
139
|
+
return false;
|
|
140
|
+
// This detector works in all browser environments
|
|
141
|
+
// It's especially useful for mobile browsers where other detectors might be less reliable
|
|
142
|
+
// It detects third-party debugging libraries and tools that might be injected
|
|
143
|
+
// No specific browser feature requirements beyond basic JS environment
|
|
144
|
+
// The detector primarily checks for global objects and properties
|
|
145
|
+
// Check if we can access the window object and its properties
|
|
146
|
+
try {
|
|
147
|
+
// Basic check to ensure we can access window properties
|
|
148
|
+
if (typeof window === "undefined" || typeof window.navigator === "undefined") {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
// If we can't access window properties (e.g., in a restricted environment)
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Default libraries to check for
|
|
161
|
+
DebugLibDetector.DEFAULT_LIBRARIES = [
|
|
162
|
+
// Mobile debugging tools
|
|
163
|
+
{ name: "Eruda", globalVar: "eruda" },
|
|
164
|
+
{ name: "vConsole", globalVar: "VConsole" },
|
|
165
|
+
{ name: "Weinre", globalVar: "weinre" },
|
|
166
|
+
{ name: "Firebug Lite", globalVar: "firebug" },
|
|
167
|
+
{ name: "Console Plus", globalVar: "ConsolePanel" },
|
|
168
|
+
// Emulators and virtualization platforms
|
|
169
|
+
{ name: "BlueStacks", globalVar: "BlueStacks" },
|
|
170
|
+
{ name: "BlueStacks Helper", globalVar: "BlueStacksGamepad" },
|
|
171
|
+
{ name: "NoxPlayer", globalVar: "NoxPlayer" },
|
|
172
|
+
{ name: "MEmu", globalVar: "MEmu" },
|
|
173
|
+
{ name: "LDPlayer", globalVar: "LDPlayer" },
|
|
174
|
+
// Remote debugging tools
|
|
175
|
+
{ name: "Vorlon", globalVar: "VORLON" },
|
|
176
|
+
{ name: "GapDebug", globalVar: "GapDebug" },
|
|
177
|
+
{ name: "Bugsnag", globalVar: "Bugsnag" },
|
|
178
|
+
{ name: "LogRocket", globalVar: "LogRocket" },
|
|
179
|
+
{ name: "Sentry", globalVar: "Sentry" },
|
|
180
|
+
// Framework-specific DevTools
|
|
181
|
+
{ name: "React DevTools", globalVar: "__REACT_DEVTOOLS_GLOBAL_HOOK__" },
|
|
182
|
+
{ name: "Redux DevTools", globalVar: "__REDUX_DEVTOOLS_EXTENSION__" },
|
|
183
|
+
{ name: "Vue DevTools", globalVar: "__VUE_DEVTOOLS_GLOBAL_HOOK__" },
|
|
184
|
+
{ name: "Angular DevTools", globalVar: "ng" },
|
|
185
|
+
{ name: "Ember Inspector", globalVar: "EmberInspector" },
|
|
186
|
+
// Mobile app debugging
|
|
187
|
+
{ name: "Flipper", globalVar: "__FLIPPER__" },
|
|
188
|
+
{ name: "Reactotron", globalVar: "reactotronClient" },
|
|
189
|
+
{ name: "Apollo DevTools", globalVar: "__APOLLO_DEVTOOLS_GLOBAL_HOOK__" },
|
|
190
|
+
{ name: "Cypress", globalVar: "Cypress" },
|
|
191
|
+
// Web proxies and network tools
|
|
192
|
+
{ name: "Fiddler", globalVar: "Fiddler" },
|
|
193
|
+
{ name: "Charles", globalVar: "Charles" },
|
|
194
|
+
{ name: "Proxyman", globalVar: "Proxyman" },
|
|
195
|
+
];
|
|
@@ -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
|
+
}
|