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.
- package/LICENSE +9 -0
- package/README.md +171 -0
- package/dist/config/default-extensions-config.json +103 -0
- package/dist/core/ContentProtector.d.ts +63 -0
- package/dist/core/ContentProtector.js +279 -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 +205 -0
- package/dist/core/mediator/eventDataTypes.js +23 -0
- package/dist/core/mediator/handlers/abstractEventHandler.d.ts +67 -0
- package/dist/core/mediator/handlers/abstractEventHandler.js +106 -0
- package/dist/core/mediator/handlers/baseEventHandler.d.ts +65 -0
- package/dist/core/mediator/handlers/baseEventHandler.js +99 -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/index.d.ts +9 -0
- package/dist/core/mediator/handlers/index.js +34 -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 +94 -0
- package/dist/core/mediator/protection-event.js +43 -0
- package/dist/core/mediator/types.d.ts +105 -0
- package/dist/core/mediator/types.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/strategies/AbstractStrategy.d.ts +152 -0
- package/dist/strategies/AbstractStrategy.js +296 -0
- package/dist/strategies/AbstractStrategy.mediator.d.ts +162 -0
- package/dist/strategies/AbstractStrategy.mediator.js +349 -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 copy.d.ts +85 -0
- package/dist/strategies/DevToolsStrategy copy.js +362 -0
- package/dist/strategies/DevToolsStrategy-detectorManager.d.ts +70 -0
- package/dist/strategies/DevToolsStrategy-detectorManager.js +309 -0
- package/dist/strategies/DevToolsStrategy-simple.d.ts +75 -0
- package/dist/strategies/DevToolsStrategy-simple.js +366 -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 +488 -0
- package/dist/strategies/SelectionStrategy.d.ts +49 -0
- package/dist/strategies/SelectionStrategy.js +216 -0
- package/dist/strategies/StrategyRegistry.d.ts +133 -0
- package/dist/strategies/StrategyRegistry.js +379 -0
- package/dist/strategies/WatermarkStrategy.d.ts +47 -0
- package/dist/strategies/WatermarkStrategy.js +273 -0
- package/dist/strategies/index.d.ts +9 -0
- package/dist/strategies/index.js +10 -0
- package/dist/types/index.d.ts +271 -0
- package/dist/types/index.js +16 -0
- package/dist/utils/DOMObserver.d.ts +68 -0
- package/dist/utils/DOMObserver.js +134 -0
- package/dist/utils/base/LoggableComponent.d.ts +62 -0
- package/dist/utils/base/LoggableComponent.js +95 -0
- package/dist/utils/debuggerDetector/debuggerDetectionWorker.d.ts +6 -0
- package/dist/utils/debuggerDetector/debuggerDetectionWorker.js +24 -0
- package/dist/utils/debuggerDetector/debuggerDetector.d.ts +55 -0
- package/dist/utils/debuggerDetector/debuggerDetector.js +158 -0
- package/dist/utils/debuggerDetector/firefoxDetector.d.ts +8 -0
- package/dist/utils/debuggerDetector/firefoxDetector.js +64 -0
- package/dist/utils/detection.d.ts +29 -0
- package/dist/utils/detection.js +267 -0
- package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +105 -0
- package/dist/utils/detectors/AbstractDevToolsDetector.js +136 -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/debuggerDetectionWorker.d.ts +6 -0
- package/dist/utils/detectors/debuggerDetectionWorker.js +24 -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 +246 -0
- package/dist/utils/detectors/firefoxDetector.d.ts +8 -0
- package/dist/utils/detectors/firefoxDetector.js +64 -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 +167 -0
- package/dist/utils/eventManager.js +556 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/intervalManager.d.ts +96 -0
- package/dist/utils/intervalManager.js +229 -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/LogLevel.d.ts +21 -0
- package/dist/utils/logging/LogLevel.js +46 -0
- package/dist/utils/logging/LoggingConfig.d.ts +68 -0
- package/dist/utils/logging/LoggingConfig.js +64 -0
- package/dist/utils/logging/LoggingFactory.d.ts +22 -0
- package/dist/utils/logging/LoggingFactory.js +61 -0
- package/dist/utils/logging/LoggingService.d.ts +235 -0
- package/dist/utils/logging/LoggingService.js +385 -0
- package/dist/utils/logging/SimpleLoggingService.d.ts +39 -0
- package/dist/utils/logging/SimpleLoggingService.js +58 -0
- package/dist/utils/logging/advanced/LogLevel.d.ts +21 -0
- package/dist/utils/logging/advanced/LogLevel.js +46 -0
- package/dist/utils/logging/advanced/LoggingConfig.d.ts +68 -0
- package/dist/utils/logging/advanced/LoggingConfig.js +64 -0
- package/dist/utils/logging/advanced/LoggingFactory.d.ts +22 -0
- package/dist/utils/logging/advanced/LoggingFactory.js +61 -0
- package/dist/utils/logging/advanced/LoggingService.d.ts +235 -0
- package/dist/utils/logging/advanced/LoggingService.js +385 -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-simple.d.ts +86 -0
- package/dist/utils/protectedContentManager-simple.js +180 -0
- package/dist/utils/protectedContentManager.d.ts +162 -0
- package/dist/utils/protectedContentManager.js +427 -0
- package/dist/utils/screenshotDetector.d.ts +72 -0
- package/dist/utils/screenshotDetector.js +179 -0
- package/dist/utils/securityOverlayManager-observer-pause.d.ts +283 -0
- package/dist/utils/securityOverlayManager-observer-pause.js +878 -0
- package/dist/utils/securityOverlayManager-simple.d.ts +197 -0
- package/dist/utils/securityOverlayManager-simple.js +552 -0
- package/dist/utils/securityOverlayManager.d.ts +260 -0
- package/dist/utils/securityOverlayManager.js +774 -0
- package/dist/utils/timeoutManager.d.ts +55 -0
- package/dist/utils/timeoutManager.js +121 -0
- package/package.json +54 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ProtectionEvent, ProtectionEventType } from './protection-event';
|
|
2
|
+
import { ProtectionEventHandler, ProtectionMediator, Subscription, SubscriptionOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Mediator for coordinating communication between protection strategies
|
|
5
|
+
* Implements the mediator pattern to decouple strategies and enable event-based communication
|
|
6
|
+
*/
|
|
7
|
+
export declare class ContentProtectionMediator implements ProtectionMediator {
|
|
8
|
+
private subscriptions;
|
|
9
|
+
private subscriptionCounter;
|
|
10
|
+
private debugMode;
|
|
11
|
+
private eventHistory;
|
|
12
|
+
private readonly MAX_HISTORY_SIZE;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new ContentProtectionMediator
|
|
15
|
+
* @param debugMode Enable debug mode for detailed logging
|
|
16
|
+
*/
|
|
17
|
+
constructor(debugMode?: boolean);
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to an event
|
|
20
|
+
* @param eventType Type of event to subscribe to
|
|
21
|
+
* @param handler Handler function for the event
|
|
22
|
+
* @param options Optional subscription options
|
|
23
|
+
* @returns Subscription ID for later unsubscribing
|
|
24
|
+
*/
|
|
25
|
+
subscribe(eventType: ProtectionEventType, handler: ProtectionEventHandler, options?: SubscriptionOptions): string;
|
|
26
|
+
/**
|
|
27
|
+
* Unsubscribe from an event
|
|
28
|
+
* @param subscriptionId ID of the subscription to remove
|
|
29
|
+
* @returns True if the subscription was found and removed
|
|
30
|
+
*/
|
|
31
|
+
unsubscribe(subscriptionId: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Unsubscribe all handlers with a specific context
|
|
34
|
+
* @param context Context to unsubscribe (e.g., strategy name)
|
|
35
|
+
* @returns Number of subscriptions removed
|
|
36
|
+
*/
|
|
37
|
+
unsubscribeByContext(context: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Publish an event to all subscribers
|
|
40
|
+
* @param event Event to publish
|
|
41
|
+
*/
|
|
42
|
+
publish(event: ProtectionEvent): void;
|
|
43
|
+
/**
|
|
44
|
+
* Get all subscriptions for a specific event type
|
|
45
|
+
* @param eventType Type of event to get subscriptions for
|
|
46
|
+
* @returns Array of subscriptions
|
|
47
|
+
*/
|
|
48
|
+
getSubscriptions(eventType: ProtectionEventType): Subscription[];
|
|
49
|
+
/**
|
|
50
|
+
* Get all subscriptions
|
|
51
|
+
* @returns Map of event types to subscriptions
|
|
52
|
+
*/
|
|
53
|
+
getAllSubscriptions(): Map<ProtectionEventType, Subscription[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Set debug mode
|
|
56
|
+
* @param enabled Whether debug mode should be enabled
|
|
57
|
+
*/
|
|
58
|
+
setDebugMode(enabled: boolean): void;
|
|
59
|
+
/**
|
|
60
|
+
* Get debug information about the mediator
|
|
61
|
+
* @returns Object with debug information
|
|
62
|
+
*/
|
|
63
|
+
getDebugInfo(): {
|
|
64
|
+
subscriptionCount: number;
|
|
65
|
+
eventTypeCount: number;
|
|
66
|
+
eventTypes: string[];
|
|
67
|
+
recentEvents: ProtectionEvent[];
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Add an event to the history
|
|
71
|
+
* @param event Event to add
|
|
72
|
+
*/
|
|
73
|
+
private addToEventHistory;
|
|
74
|
+
/**
|
|
75
|
+
* Clear all subscriptions
|
|
76
|
+
* @returns Number of subscriptions cleared
|
|
77
|
+
*/
|
|
78
|
+
clearAllSubscriptions(): number;
|
|
79
|
+
/**
|
|
80
|
+
* Helper method to create and publish an event
|
|
81
|
+
* @param type Event type
|
|
82
|
+
* @param source Source of the event
|
|
83
|
+
* @param data Additional data
|
|
84
|
+
*/
|
|
85
|
+
createAndPublishEvent(type: ProtectionEventType, source: string, data?: unknown): void;
|
|
86
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mediator for coordinating communication between protection strategies
|
|
3
|
+
* Implements the mediator pattern to decouple strategies and enable event-based communication
|
|
4
|
+
*/
|
|
5
|
+
export class ContentProtectionMediator {
|
|
6
|
+
/**
|
|
7
|
+
* Create a new ContentProtectionMediator
|
|
8
|
+
* @param debugMode Enable debug mode for detailed logging
|
|
9
|
+
*/
|
|
10
|
+
constructor(debugMode = false) {
|
|
11
|
+
this.subscriptions = new Map();
|
|
12
|
+
this.subscriptionCounter = 0;
|
|
13
|
+
this.eventHistory = [];
|
|
14
|
+
this.MAX_HISTORY_SIZE = 100;
|
|
15
|
+
this.debugMode = debugMode;
|
|
16
|
+
if (this.debugMode) {
|
|
17
|
+
console.log('ContentProtectionMediator: Initialized');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Subscribe to an event
|
|
22
|
+
* @param eventType Type of event to subscribe to
|
|
23
|
+
* @param handler Handler function for the event
|
|
24
|
+
* @param options Optional subscription options
|
|
25
|
+
* @returns Subscription ID for later unsubscribing
|
|
26
|
+
*/
|
|
27
|
+
subscribe(eventType, handler, options) {
|
|
28
|
+
if (!handler || typeof handler !== 'function') {
|
|
29
|
+
console.error('ContentProtectionMediator: Invalid handler provided to subscribe');
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
// Generate a unique subscription ID
|
|
33
|
+
const subscriptionId = `sub_${++this.subscriptionCounter}`;
|
|
34
|
+
// Create the subscription object
|
|
35
|
+
const subscription = {
|
|
36
|
+
id: subscriptionId,
|
|
37
|
+
eventType,
|
|
38
|
+
handler,
|
|
39
|
+
filter: options?.filter,
|
|
40
|
+
priority: options?.priority || 0,
|
|
41
|
+
context: options?.context
|
|
42
|
+
};
|
|
43
|
+
// Get or create the array of subscriptions for this event type
|
|
44
|
+
if (!this.subscriptions.has(eventType)) {
|
|
45
|
+
this.subscriptions.set(eventType, []);
|
|
46
|
+
}
|
|
47
|
+
// Add the subscription to the array
|
|
48
|
+
const subscriptionsForType = this.subscriptions.get(eventType);
|
|
49
|
+
subscriptionsForType.push(subscription);
|
|
50
|
+
// Sort by priority (higher numbers first)
|
|
51
|
+
subscriptionsForType.sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
52
|
+
if (this.debugMode) {
|
|
53
|
+
console.log(`ContentProtectionMediator: Subscribed to ${eventType} with ID ${subscriptionId}`, options ? `(priority: ${options.priority || 0}, context: ${options.context || 'none'})` : '');
|
|
54
|
+
}
|
|
55
|
+
return subscriptionId;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Unsubscribe from an event
|
|
59
|
+
* @param subscriptionId ID of the subscription to remove
|
|
60
|
+
* @returns True if the subscription was found and removed
|
|
61
|
+
*/
|
|
62
|
+
unsubscribe(subscriptionId) {
|
|
63
|
+
if (!subscriptionId)
|
|
64
|
+
return false;
|
|
65
|
+
let found = false;
|
|
66
|
+
// Check all event types
|
|
67
|
+
for (const [eventType, subscriptions] of this.subscriptions.entries()) {
|
|
68
|
+
const initialLength = subscriptions.length;
|
|
69
|
+
// Filter out the subscription with the given ID
|
|
70
|
+
const filteredSubscriptions = subscriptions.filter(sub => sub.id !== subscriptionId);
|
|
71
|
+
if (filteredSubscriptions.length < initialLength) {
|
|
72
|
+
// We found and removed the subscription
|
|
73
|
+
this.subscriptions.set(eventType, filteredSubscriptions);
|
|
74
|
+
found = true;
|
|
75
|
+
if (this.debugMode) {
|
|
76
|
+
console.log(`ContentProtectionMediator: Unsubscribed from ${eventType} with ID ${subscriptionId}`);
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return found;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Unsubscribe all handlers with a specific context
|
|
85
|
+
* @param context Context to unsubscribe (e.g., strategy name)
|
|
86
|
+
* @returns Number of subscriptions removed
|
|
87
|
+
*/
|
|
88
|
+
unsubscribeByContext(context) {
|
|
89
|
+
if (!context)
|
|
90
|
+
return 0;
|
|
91
|
+
let removedCount = 0;
|
|
92
|
+
// Check all event types
|
|
93
|
+
for (const [eventType, subscriptions] of this.subscriptions.entries()) {
|
|
94
|
+
const initialLength = subscriptions.length;
|
|
95
|
+
// Filter out subscriptions with the given context
|
|
96
|
+
const filteredSubscriptions = subscriptions.filter(sub => sub.context !== context);
|
|
97
|
+
if (filteredSubscriptions.length < initialLength) {
|
|
98
|
+
// We found and removed subscriptions
|
|
99
|
+
const removed = initialLength - filteredSubscriptions.length;
|
|
100
|
+
removedCount += removed;
|
|
101
|
+
this.subscriptions.set(eventType, filteredSubscriptions);
|
|
102
|
+
if (this.debugMode) {
|
|
103
|
+
console.log(`ContentProtectionMediator: Unsubscribed ${removed} handlers for ${context} from ${eventType}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return removedCount;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Publish an event to all subscribers
|
|
111
|
+
* @param event Event to publish
|
|
112
|
+
*/
|
|
113
|
+
publish(event) {
|
|
114
|
+
console.log('Publishing event', event);
|
|
115
|
+
if (!event || !event.type) {
|
|
116
|
+
console.error('ContentProtectionMediator: Invalid event provided to publish');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Add timestamp if not provided
|
|
120
|
+
if (!event.timestamp) {
|
|
121
|
+
event.timestamp = Date.now();
|
|
122
|
+
}
|
|
123
|
+
// Store in history for debugging
|
|
124
|
+
this.addToEventHistory(event);
|
|
125
|
+
// Get subscriptions for this event type
|
|
126
|
+
const subscriptions = this.subscriptions.get(event.type) || [];
|
|
127
|
+
if (subscriptions.length === 0) {
|
|
128
|
+
if (this.debugMode) {
|
|
129
|
+
console.log(`ContentProtectionMediator: No subscribers for ${event.type}`);
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (this.debugMode) {
|
|
134
|
+
console.log(`ContentProtectionMediator: Publishing ${event.type} from ${event.source}`, event.data ? `with data: ${JSON.stringify(event.data)}` : '');
|
|
135
|
+
}
|
|
136
|
+
// Call each handler
|
|
137
|
+
for (const subscription of subscriptions) {
|
|
138
|
+
try {
|
|
139
|
+
// Apply filter if provided
|
|
140
|
+
if (subscription.filter && !subscription.filter(event)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Call the handler
|
|
144
|
+
subscription.handler(event);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error(`ContentProtectionMediator: Error in handler for ${event.type}:`, error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get all subscriptions for a specific event type
|
|
153
|
+
* @param eventType Type of event to get subscriptions for
|
|
154
|
+
* @returns Array of subscriptions
|
|
155
|
+
*/
|
|
156
|
+
getSubscriptions(eventType) {
|
|
157
|
+
return [...(this.subscriptions.get(eventType) || [])];
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get all subscriptions
|
|
161
|
+
* @returns Map of event types to subscriptions
|
|
162
|
+
*/
|
|
163
|
+
getAllSubscriptions() {
|
|
164
|
+
// Return a deep copy to prevent external modification
|
|
165
|
+
const result = new Map();
|
|
166
|
+
for (const [eventType, subscriptions] of this.subscriptions.entries()) {
|
|
167
|
+
result.set(eventType, [...subscriptions]);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Set debug mode
|
|
173
|
+
* @param enabled Whether debug mode should be enabled
|
|
174
|
+
*/
|
|
175
|
+
setDebugMode(enabled) {
|
|
176
|
+
this.debugMode = enabled;
|
|
177
|
+
if (this.debugMode) {
|
|
178
|
+
console.log('ContentProtectionMediator: Debug mode enabled');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get debug information about the mediator
|
|
183
|
+
* @returns Object with debug information
|
|
184
|
+
*/
|
|
185
|
+
getDebugInfo() {
|
|
186
|
+
let totalSubscriptions = 0;
|
|
187
|
+
for (const subscriptions of this.subscriptions.values()) {
|
|
188
|
+
totalSubscriptions += subscriptions.length;
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
subscriptionCount: totalSubscriptions,
|
|
192
|
+
eventTypeCount: this.subscriptions.size,
|
|
193
|
+
eventTypes: Array.from(this.subscriptions.keys()),
|
|
194
|
+
recentEvents: [...this.eventHistory]
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Add an event to the history
|
|
199
|
+
* @param event Event to add
|
|
200
|
+
*/
|
|
201
|
+
addToEventHistory(event) {
|
|
202
|
+
this.eventHistory.unshift(event);
|
|
203
|
+
// Limit history size
|
|
204
|
+
if (this.eventHistory.length > this.MAX_HISTORY_SIZE) {
|
|
205
|
+
this.eventHistory.pop();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Clear all subscriptions
|
|
210
|
+
* @returns Number of subscriptions cleared
|
|
211
|
+
*/
|
|
212
|
+
clearAllSubscriptions() {
|
|
213
|
+
let count = 0;
|
|
214
|
+
for (const subscriptions of this.subscriptions.values()) {
|
|
215
|
+
count += subscriptions.length;
|
|
216
|
+
}
|
|
217
|
+
this.subscriptions.clear();
|
|
218
|
+
if (this.debugMode) {
|
|
219
|
+
console.log(`ContentProtectionMediator: Cleared ${count} subscriptions`);
|
|
220
|
+
}
|
|
221
|
+
return count;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Helper method to create and publish an event
|
|
225
|
+
* @param type Event type
|
|
226
|
+
* @param source Source of the event
|
|
227
|
+
* @param data Additional data
|
|
228
|
+
*/
|
|
229
|
+
createAndPublishEvent(type, source, data) {
|
|
230
|
+
const event = {
|
|
231
|
+
type,
|
|
232
|
+
source,
|
|
233
|
+
timestamp: Date.now(),
|
|
234
|
+
data
|
|
235
|
+
};
|
|
236
|
+
this.publish(event);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { OverlayOptions } from "@/utils/securityOverlayManager";
|
|
2
|
+
import { ProtectionEventType } from "./protection-event";
|
|
3
|
+
import { PlaceholderOptions } from "@/utils/protectedContentManager";
|
|
4
|
+
import { ExtensionConfig } from "@/types";
|
|
5
|
+
/**
|
|
6
|
+
* Interface defining the data structure for each event type
|
|
7
|
+
*/
|
|
8
|
+
export interface EventDataMap {
|
|
9
|
+
[ProtectionEventType.DEVTOOLS_STATE_CHANGE]: {
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
target?: HTMLElement | null;
|
|
12
|
+
showOverlay?: boolean | null;
|
|
13
|
+
overlayOptions?: OverlayOptions | null;
|
|
14
|
+
hideContent?: boolean | null;
|
|
15
|
+
};
|
|
16
|
+
[ProtectionEventType.EXTENSION_DETECTED]: {
|
|
17
|
+
extension: ExtensionConfig | null;
|
|
18
|
+
showOverlay?: boolean | null;
|
|
19
|
+
overlayOptions?: OverlayOptions | null;
|
|
20
|
+
hideContent?: boolean | null;
|
|
21
|
+
priority: number;
|
|
22
|
+
reason: string;
|
|
23
|
+
target?: HTMLElement | null;
|
|
24
|
+
};
|
|
25
|
+
[ProtectionEventType.SCREENSHOT_ATTEMPT]: {
|
|
26
|
+
showOverlay?: boolean | null;
|
|
27
|
+
hideContent?: boolean | null;
|
|
28
|
+
overlayOptions?: OverlayOptions | null;
|
|
29
|
+
duration?: number | null;
|
|
30
|
+
priority: number;
|
|
31
|
+
reason: string;
|
|
32
|
+
target?: HTMLElement | null;
|
|
33
|
+
};
|
|
34
|
+
[ProtectionEventType.FRAME_EMBEDDING_DETECTED]: {
|
|
35
|
+
isEmbedded: boolean;
|
|
36
|
+
isExternalFrame: boolean;
|
|
37
|
+
parentDomain?: string;
|
|
38
|
+
targetElement?: HTMLElement | null;
|
|
39
|
+
showOverlay?: boolean | null;
|
|
40
|
+
hideContent?: boolean | null;
|
|
41
|
+
overlayOptions?: OverlayOptions | null;
|
|
42
|
+
};
|
|
43
|
+
[ProtectionEventType.CONTENT_HIDDEN]: {
|
|
44
|
+
strategyName: string;
|
|
45
|
+
reason: string;
|
|
46
|
+
options: PlaceholderOptions;
|
|
47
|
+
targetElement?: HTMLElement | null;
|
|
48
|
+
priority: number;
|
|
49
|
+
};
|
|
50
|
+
[ProtectionEventType.CONTENT_RESTORED]: {
|
|
51
|
+
strategyName: string;
|
|
52
|
+
targetElement?: HTMLElement | null;
|
|
53
|
+
};
|
|
54
|
+
[ProtectionEventType.OVERLAY_SHOWN]: {
|
|
55
|
+
strategyName: string;
|
|
56
|
+
overlayType: string;
|
|
57
|
+
options: OverlayOptions;
|
|
58
|
+
priority: number;
|
|
59
|
+
duration?: number;
|
|
60
|
+
};
|
|
61
|
+
[ProtectionEventType.OVERLAY_REMOVED]: {
|
|
62
|
+
strategyName: string;
|
|
63
|
+
overlayType: string;
|
|
64
|
+
reason?: string;
|
|
65
|
+
};
|
|
66
|
+
[ProtectionEventType.MEDIATOR_INITIALIZED]: {
|
|
67
|
+
strategies: string[];
|
|
68
|
+
};
|
|
69
|
+
[ProtectionEventType.MEDIATOR_DISPOSED]: {
|
|
70
|
+
reason?: string;
|
|
71
|
+
};
|
|
72
|
+
[ProtectionEventType.KEYBOARD_SHORTCUTS_REQUESTED]: {
|
|
73
|
+
requestingStrategy: string;
|
|
74
|
+
categories?: string[];
|
|
75
|
+
};
|
|
76
|
+
[ProtectionEventType.KEYBOARD_SHORTCUTS_PROVIDED]: {
|
|
77
|
+
providingStrategy: string;
|
|
78
|
+
shortcuts: Array<{
|
|
79
|
+
id: string;
|
|
80
|
+
keys: string[];
|
|
81
|
+
description: string;
|
|
82
|
+
category: string;
|
|
83
|
+
}>;
|
|
84
|
+
};
|
|
85
|
+
[ProtectionEventType.KEYBOARD_SHORTCUTS_UPDATED]: {
|
|
86
|
+
updatingStrategy: string;
|
|
87
|
+
addedShortcuts?: Array<{
|
|
88
|
+
id: string;
|
|
89
|
+
keys: string[];
|
|
90
|
+
description: string;
|
|
91
|
+
category: string;
|
|
92
|
+
}>;
|
|
93
|
+
removedShortcutIds?: string[];
|
|
94
|
+
};
|
|
95
|
+
[ProtectionEventType.STRATEGY_APPLIED]: {
|
|
96
|
+
strategyName: string;
|
|
97
|
+
options?: Record<string, unknown>;
|
|
98
|
+
};
|
|
99
|
+
[ProtectionEventType.STRATEGY_REMOVED]: {
|
|
100
|
+
strategyName: string;
|
|
101
|
+
reason?: string;
|
|
102
|
+
};
|
|
103
|
+
[ProtectionEventType.STRATEGY_UPDATED]: {
|
|
104
|
+
strategyName: string;
|
|
105
|
+
changes: Record<string, unknown>;
|
|
106
|
+
};
|
|
107
|
+
[ProtectionEventType.CONTEXT_MENU_ATTEMPT]: {
|
|
108
|
+
target?: HTMLElement | null;
|
|
109
|
+
prevented: boolean;
|
|
110
|
+
};
|
|
111
|
+
[ProtectionEventType.SELECTION_ATTEMPT]: {
|
|
112
|
+
target?: HTMLElement | null;
|
|
113
|
+
selectedText?: string;
|
|
114
|
+
prevented: boolean;
|
|
115
|
+
};
|
|
116
|
+
[ProtectionEventType.DRAG_ATTEMPT]: {
|
|
117
|
+
target?: HTMLElement | null;
|
|
118
|
+
prevented: boolean;
|
|
119
|
+
};
|
|
120
|
+
[ProtectionEventType.KEYBOARD_SHORTCUT_BLOCKED]: {
|
|
121
|
+
key: string;
|
|
122
|
+
code: string;
|
|
123
|
+
ctrlKey: boolean;
|
|
124
|
+
altKey: boolean;
|
|
125
|
+
shiftKey: boolean;
|
|
126
|
+
metaKey: boolean;
|
|
127
|
+
shortcutId?: string;
|
|
128
|
+
category?: string;
|
|
129
|
+
};
|
|
130
|
+
[ProtectionEventType.PRINT_ATTEMPT]: {
|
|
131
|
+
prevented: boolean;
|
|
132
|
+
reason?: string;
|
|
133
|
+
};
|
|
134
|
+
[ProtectionEventType.FULLSCREEN_CHANGE]: {
|
|
135
|
+
isFullscreen: boolean;
|
|
136
|
+
prevented: boolean;
|
|
137
|
+
reason?: string;
|
|
138
|
+
};
|
|
139
|
+
[ProtectionEventType.WATERMARK_TAMPERED]: {
|
|
140
|
+
watermarkId: string;
|
|
141
|
+
tamperedElement?: HTMLElement | null;
|
|
142
|
+
originalContent?: string;
|
|
143
|
+
};
|
|
144
|
+
[ProtectionEventType.OVERLAY_RESTORED]: {
|
|
145
|
+
strategyName: string;
|
|
146
|
+
overlayType: string;
|
|
147
|
+
reason?: string;
|
|
148
|
+
};
|
|
149
|
+
[ProtectionEventType.WATERMARK_CREATED]: {
|
|
150
|
+
watermarkId: string;
|
|
151
|
+
targetElement?: HTMLElement | null;
|
|
152
|
+
options?: Record<string, unknown>;
|
|
153
|
+
};
|
|
154
|
+
[ProtectionEventType.WATERMARK_REMOVED]: {
|
|
155
|
+
watermarkId: string;
|
|
156
|
+
reason?: string;
|
|
157
|
+
};
|
|
158
|
+
[ProtectionEventType.ERROR_OCCURRED]: {
|
|
159
|
+
error: Error | string;
|
|
160
|
+
source: string;
|
|
161
|
+
context?: Record<string, unknown>;
|
|
162
|
+
};
|
|
163
|
+
[ProtectionEventType.DEBUG_MESSAGE]: {
|
|
164
|
+
message: string;
|
|
165
|
+
level: "log" | "warn" | "error" | "info";
|
|
166
|
+
data?: unknown;
|
|
167
|
+
};
|
|
168
|
+
[ProtectionEventType.CONFIG_UPDATED]: {
|
|
169
|
+
configKey: string;
|
|
170
|
+
oldValue?: unknown;
|
|
171
|
+
newValue: unknown;
|
|
172
|
+
};
|
|
173
|
+
[key: string]: Record<string, unknown>;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Type-safe typed event interface
|
|
177
|
+
* Use this instead of unsafe `as` assertions
|
|
178
|
+
*/
|
|
179
|
+
export interface TypedProtectionEvent<T extends ProtectionEventType> {
|
|
180
|
+
type: T;
|
|
181
|
+
source: string;
|
|
182
|
+
timestamp: number;
|
|
183
|
+
data: EventDataMap[T];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Type guard to check if an event has a specific type
|
|
187
|
+
* @param event The event to check
|
|
188
|
+
* @param eventType The expected event type
|
|
189
|
+
* @returns True if the event matches the type
|
|
190
|
+
*/
|
|
191
|
+
export declare function isEventType<T extends ProtectionEventType>(event: {
|
|
192
|
+
type: ProtectionEventType;
|
|
193
|
+
data?: unknown;
|
|
194
|
+
}, eventType: T): event is TypedProtectionEvent<T>;
|
|
195
|
+
/**
|
|
196
|
+
* Get typed event data with type safety
|
|
197
|
+
* Returns undefined if the event type doesn't match
|
|
198
|
+
* @param event The protection event
|
|
199
|
+
* @param eventType The expected event type
|
|
200
|
+
* @returns The typed data or undefined
|
|
201
|
+
*/
|
|
202
|
+
export declare function getTypedEventData<T extends ProtectionEventType>(event: {
|
|
203
|
+
type: ProtectionEventType;
|
|
204
|
+
data?: unknown;
|
|
205
|
+
}, eventType: T): EventDataMap[T] | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ProtectionEventType } from "./protection-event";
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if an event has a specific type
|
|
4
|
+
* @param event The event to check
|
|
5
|
+
* @param eventType The expected event type
|
|
6
|
+
* @returns True if the event matches the type
|
|
7
|
+
*/
|
|
8
|
+
export function isEventType(event, eventType) {
|
|
9
|
+
return event.type === eventType;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get typed event data with type safety
|
|
13
|
+
* Returns undefined if the event type doesn't match
|
|
14
|
+
* @param event The protection event
|
|
15
|
+
* @param eventType The expected event type
|
|
16
|
+
* @returns The typed data or undefined
|
|
17
|
+
*/
|
|
18
|
+
export function getTypedEventData(event, eventType) {
|
|
19
|
+
if (event.type === eventType) {
|
|
20
|
+
return event.data;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ProtectionMediator } from "../types";
|
|
2
|
+
import type { ProtectionEvent, ProtectionEventType } from "../protection-event";
|
|
3
|
+
import { SimpleLoggingService } from "../../../utils/logging/simple/SimpleLoggingService";
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class for all event handlers
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class AbstractEventHandler {
|
|
8
|
+
protected mediator: ProtectionMediator;
|
|
9
|
+
protected readonly COMPONENT_NAME: string;
|
|
10
|
+
protected logger: SimpleLoggingService;
|
|
11
|
+
protected debugMode: boolean;
|
|
12
|
+
protected subscriptionIds: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Create a new event handler
|
|
15
|
+
* @param mediator The protection mediator
|
|
16
|
+
* @param componentName The name of the component
|
|
17
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
18
|
+
*/
|
|
19
|
+
constructor(mediator: ProtectionMediator, componentName: string, debugMode?: boolean);
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the handler and subscribe to events
|
|
22
|
+
* This method should be implemented by subclasses
|
|
23
|
+
*/
|
|
24
|
+
protected abstract initialize(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Set debug mode
|
|
27
|
+
* @param enabled Whether debug mode should be enabled
|
|
28
|
+
*/
|
|
29
|
+
setDebugMode(enabled: boolean): void;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to an event and track the subscription ID
|
|
32
|
+
* @param eventType The event type to subscribe to
|
|
33
|
+
* @param handler The event handler function
|
|
34
|
+
* @param options Optional subscription options
|
|
35
|
+
* @returns The subscription ID
|
|
36
|
+
*/
|
|
37
|
+
protected subscribe(eventType: ProtectionEventType, handler: (event: ProtectionEvent) => void, options?: {
|
|
38
|
+
context?: string;
|
|
39
|
+
}): string;
|
|
40
|
+
/**
|
|
41
|
+
* Log a debug message if debug mode is enabled
|
|
42
|
+
* @param message Message to log
|
|
43
|
+
* @param args Additional arguments to log
|
|
44
|
+
*/
|
|
45
|
+
protected log(message: string, ...args: unknown[]): void;
|
|
46
|
+
/**
|
|
47
|
+
* Log a warning message
|
|
48
|
+
* @param message Warning message
|
|
49
|
+
* @param args Additional arguments to log
|
|
50
|
+
*/
|
|
51
|
+
protected warn(message: string, ...args: unknown[]): void;
|
|
52
|
+
/**
|
|
53
|
+
* Log an error message
|
|
54
|
+
* @param message Error message
|
|
55
|
+
* @param args Additional arguments to log
|
|
56
|
+
*/
|
|
57
|
+
protected error(message: string, ...args: unknown[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Unsubscribe from all events and clean up
|
|
60
|
+
*/
|
|
61
|
+
dispose(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Additional cleanup to be performed on disposal
|
|
64
|
+
* This method can be overridden by subclasses
|
|
65
|
+
*/
|
|
66
|
+
protected onDispose(): void;
|
|
67
|
+
}
|