@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,67 @@
|
|
|
1
|
+
import { AbstractStrategy } from "./AbstractStrategy";
|
|
2
|
+
import type { ClipboardOptions } from "../types";
|
|
3
|
+
import type { CustomEventHandlers } from "../types";
|
|
4
|
+
/**
|
|
5
|
+
* Strategy to prevent copying content via clipboard operations
|
|
6
|
+
* Blocks copy, cut, and optionally paste operations
|
|
7
|
+
*/
|
|
8
|
+
export declare class ClipboardStrategy extends AbstractStrategy {
|
|
9
|
+
private options;
|
|
10
|
+
private targetElement;
|
|
11
|
+
private customHandler?;
|
|
12
|
+
private originalClipboardWriteText;
|
|
13
|
+
private originalClipboardReadText;
|
|
14
|
+
private originalExecCommand;
|
|
15
|
+
/**
|
|
16
|
+
* Create a new ClipboardStrategy
|
|
17
|
+
* @param options Configuration options
|
|
18
|
+
* @param targetElement Target element to protect (defaults to document.body)
|
|
19
|
+
* @param customHandler Custom handler for clipboard events
|
|
20
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
21
|
+
*/
|
|
22
|
+
constructor(options?: ClipboardOptions, targetElement?: HTMLElement | null, customHandler?: CustomEventHandlers["onClipboardAttempt"], debugMode?: boolean);
|
|
23
|
+
/**
|
|
24
|
+
* Apply clipboard protection
|
|
25
|
+
*/
|
|
26
|
+
apply(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove clipboard protection
|
|
29
|
+
*/
|
|
30
|
+
remove(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Update clipboard protection options
|
|
33
|
+
* @param options New options to apply
|
|
34
|
+
*/
|
|
35
|
+
updateOptions(options: Partial<ClipboardOptions>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Handle copy event
|
|
38
|
+
* @param event Copy event
|
|
39
|
+
*/
|
|
40
|
+
private handleCopy;
|
|
41
|
+
/**
|
|
42
|
+
* Handle cut event
|
|
43
|
+
* @param event Cut event
|
|
44
|
+
*/
|
|
45
|
+
private handleCut;
|
|
46
|
+
/**
|
|
47
|
+
* Handle paste event
|
|
48
|
+
* @param event Paste event
|
|
49
|
+
*/
|
|
50
|
+
private handlePaste;
|
|
51
|
+
/**
|
|
52
|
+
* Intercept the Clipboard API to prevent programmatic access
|
|
53
|
+
*/
|
|
54
|
+
private interceptClipboardAPI;
|
|
55
|
+
/**
|
|
56
|
+
* Restore original Clipboard API methods
|
|
57
|
+
*/
|
|
58
|
+
private restoreClipboardAPI;
|
|
59
|
+
/**
|
|
60
|
+
* Intercept document.execCommand to prevent clipboard operations
|
|
61
|
+
*/
|
|
62
|
+
private interceptExecCommand;
|
|
63
|
+
/**
|
|
64
|
+
* Restore original document.execCommand
|
|
65
|
+
*/
|
|
66
|
+
private restoreExecCommand;
|
|
67
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { AbstractStrategy, StrategyErrorType } from "./AbstractStrategy";
|
|
2
|
+
import { isBrowser } from "../utils/environment";
|
|
3
|
+
/**
|
|
4
|
+
* Strategy to prevent copying content via clipboard operations
|
|
5
|
+
* Blocks copy, cut, and optionally paste operations
|
|
6
|
+
*/
|
|
7
|
+
export class ClipboardStrategy extends AbstractStrategy {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new ClipboardStrategy
|
|
10
|
+
* @param options Configuration options
|
|
11
|
+
* @param targetElement Target element to protect (defaults to document.body)
|
|
12
|
+
* @param customHandler Custom handler for clipboard events
|
|
13
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
14
|
+
*/
|
|
15
|
+
constructor(options = {}, targetElement, customHandler, debugMode = false) {
|
|
16
|
+
super("ClipboardStrategy", debugMode);
|
|
17
|
+
this.originalClipboardWriteText = null;
|
|
18
|
+
this.originalClipboardReadText = null;
|
|
19
|
+
this.originalExecCommand = null;
|
|
20
|
+
// Set default options
|
|
21
|
+
this.options = {
|
|
22
|
+
preventCopy: true,
|
|
23
|
+
preventCut: true,
|
|
24
|
+
preventPaste: false,
|
|
25
|
+
replacementText: "Content copying is disabled for security reasons.",
|
|
26
|
+
...options,
|
|
27
|
+
};
|
|
28
|
+
this.targetElement = targetElement || (isBrowser() ? document.body : null);
|
|
29
|
+
this.customHandler = customHandler;
|
|
30
|
+
this.log("Initialized with options:", this.options);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Apply clipboard protection
|
|
34
|
+
*/
|
|
35
|
+
apply() {
|
|
36
|
+
this.safeExecute("apply", StrategyErrorType.APPLICATION, () => {
|
|
37
|
+
if (this.isAppliedFlag || !this.targetElement || !isBrowser()) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.log("Applying clipboard protection");
|
|
41
|
+
// Register clipboard events
|
|
42
|
+
if (this.options.preventCopy) {
|
|
43
|
+
this.registerEvent(this.targetElement, "copy", this.handleCopy.bind(this), {
|
|
44
|
+
capture: true,
|
|
45
|
+
passive: false,
|
|
46
|
+
priority: 10,
|
|
47
|
+
});
|
|
48
|
+
this.log("Registered copy event handler");
|
|
49
|
+
}
|
|
50
|
+
if (this.options.preventCut) {
|
|
51
|
+
this.registerEvent(this.targetElement, "cut", this.handleCut.bind(this), {
|
|
52
|
+
capture: true,
|
|
53
|
+
passive: false,
|
|
54
|
+
priority: 10,
|
|
55
|
+
});
|
|
56
|
+
this.log("Registered cut event handler");
|
|
57
|
+
}
|
|
58
|
+
if (this.options.preventPaste) {
|
|
59
|
+
this.registerEvent(this.targetElement, "paste", this.handlePaste.bind(this), {
|
|
60
|
+
capture: true,
|
|
61
|
+
passive: false,
|
|
62
|
+
priority: 10,
|
|
63
|
+
});
|
|
64
|
+
this.log("Registered paste event handler");
|
|
65
|
+
}
|
|
66
|
+
// Always intercept Clipboard API
|
|
67
|
+
this.interceptClipboardAPI();
|
|
68
|
+
// Intercept document.execCommand
|
|
69
|
+
this.interceptExecCommand();
|
|
70
|
+
this.isAppliedFlag = true;
|
|
71
|
+
this.log(`Protection applied with ${this.eventIds.length} event handlers`);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Remove clipboard protection
|
|
76
|
+
*/
|
|
77
|
+
remove() {
|
|
78
|
+
this.safeExecute("remove", StrategyErrorType.REMOVAL, () => {
|
|
79
|
+
if (!this.isAppliedFlag) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Restore original Clipboard API methods if they were intercepted
|
|
83
|
+
this.restoreClipboardAPI();
|
|
84
|
+
// Restore original execCommand if it was intercepted
|
|
85
|
+
this.restoreExecCommand();
|
|
86
|
+
// Remove event listeners
|
|
87
|
+
super.remove();
|
|
88
|
+
this.log("Clipboard protection removed");
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Update clipboard protection options
|
|
93
|
+
* @param options New options to apply
|
|
94
|
+
*/
|
|
95
|
+
updateOptions(options) {
|
|
96
|
+
this.safeExecute("updateOptions", StrategyErrorType.OPTION_UPDATE, () => {
|
|
97
|
+
const wasApplied = this.isAppliedFlag;
|
|
98
|
+
// Remove current protection
|
|
99
|
+
if (wasApplied) {
|
|
100
|
+
this.remove();
|
|
101
|
+
}
|
|
102
|
+
// Update options
|
|
103
|
+
this.options = {
|
|
104
|
+
...this.options,
|
|
105
|
+
...options,
|
|
106
|
+
};
|
|
107
|
+
this.log("Options updated:", this.options);
|
|
108
|
+
// Reapply protection if it was applied before
|
|
109
|
+
if (wasApplied) {
|
|
110
|
+
this.apply();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handle copy event
|
|
116
|
+
* @param event Copy event
|
|
117
|
+
*/
|
|
118
|
+
handleCopy(event) {
|
|
119
|
+
this.safeExecute("handleCopy", StrategyErrorType.EVENT_HANDLING, () => {
|
|
120
|
+
const e = event;
|
|
121
|
+
this.log("Copy attempt detected", { target: e.target });
|
|
122
|
+
// Call custom handler if provided
|
|
123
|
+
if (this.customHandler) {
|
|
124
|
+
this.customHandler(e, "copy");
|
|
125
|
+
}
|
|
126
|
+
// Prevent default copy behavior
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
// Replace clipboard content if supported
|
|
130
|
+
if (e.clipboardData) {
|
|
131
|
+
e.clipboardData.setData("text/plain", this.options.replacementText || "");
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Handle cut event
|
|
138
|
+
* @param event Cut event
|
|
139
|
+
*/
|
|
140
|
+
handleCut(event) {
|
|
141
|
+
this.safeExecute("handleCut", StrategyErrorType.EVENT_HANDLING, () => {
|
|
142
|
+
const e = event;
|
|
143
|
+
this.log("Cut attempt detected", { target: e.target });
|
|
144
|
+
// Call custom handler if provided
|
|
145
|
+
if (this.customHandler) {
|
|
146
|
+
this.customHandler(e, "cut");
|
|
147
|
+
}
|
|
148
|
+
// Prevent default cut behavior
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
// Replace clipboard content if supported
|
|
152
|
+
if (e.clipboardData) {
|
|
153
|
+
e.clipboardData.setData("text/plain", this.options.replacementText || "");
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Handle paste event
|
|
160
|
+
* @param event Paste event
|
|
161
|
+
*/
|
|
162
|
+
handlePaste(event) {
|
|
163
|
+
this.safeExecute("handlePaste", StrategyErrorType.EVENT_HANDLING, () => {
|
|
164
|
+
const e = event;
|
|
165
|
+
this.log("Paste attempt detected", { target: e.target });
|
|
166
|
+
// Call custom handler if provided
|
|
167
|
+
if (this.customHandler) {
|
|
168
|
+
this.customHandler(e, "paste");
|
|
169
|
+
}
|
|
170
|
+
// Prevent default paste behavior
|
|
171
|
+
e.preventDefault();
|
|
172
|
+
e.stopPropagation();
|
|
173
|
+
return false;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Intercept the Clipboard API to prevent programmatic access
|
|
178
|
+
*/
|
|
179
|
+
interceptClipboardAPI() {
|
|
180
|
+
this.safeExecute("interceptClipboardAPI", StrategyErrorType.APPLICATION, () => {
|
|
181
|
+
if (!isBrowser() || !navigator.clipboard) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
this.log("Intercepting Clipboard API");
|
|
185
|
+
// Store original methods
|
|
186
|
+
if (navigator.clipboard.writeText) {
|
|
187
|
+
this.originalClipboardWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
|
|
188
|
+
// Override writeText
|
|
189
|
+
navigator.clipboard.writeText = async (text) => {
|
|
190
|
+
this.log("Clipboard API writeText intercepted");
|
|
191
|
+
// Call custom handler if provided
|
|
192
|
+
if (this.customHandler) {
|
|
193
|
+
const mockEvent = new ClipboardEvent("copy");
|
|
194
|
+
this.customHandler(mockEvent, "copy");
|
|
195
|
+
}
|
|
196
|
+
// Return a resolved promise with the replacement text if copy is prevented
|
|
197
|
+
if (this.options.preventCopy) {
|
|
198
|
+
return Promise.resolve();
|
|
199
|
+
}
|
|
200
|
+
// Otherwise use the original method
|
|
201
|
+
return this.originalClipboardWriteText(text);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Intercept readText if paste prevention is enabled
|
|
205
|
+
if (this.options.preventPaste && navigator.clipboard.readText) {
|
|
206
|
+
this.originalClipboardReadText = navigator.clipboard.readText.bind(navigator.clipboard);
|
|
207
|
+
// Override readText
|
|
208
|
+
navigator.clipboard.readText = async () => {
|
|
209
|
+
this.log("Clipboard API readText intercepted");
|
|
210
|
+
// Call custom handler if provided
|
|
211
|
+
if (this.customHandler) {
|
|
212
|
+
const mockEvent = new ClipboardEvent("paste");
|
|
213
|
+
this.customHandler(mockEvent, "paste");
|
|
214
|
+
}
|
|
215
|
+
// Return empty string if paste is prevented
|
|
216
|
+
if (this.options.preventPaste) {
|
|
217
|
+
return Promise.resolve("");
|
|
218
|
+
}
|
|
219
|
+
// Otherwise use the original method
|
|
220
|
+
return this.originalClipboardReadText();
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Restore original Clipboard API methods
|
|
227
|
+
*/
|
|
228
|
+
restoreClipboardAPI() {
|
|
229
|
+
this.safeExecute("restoreClipboardAPI", StrategyErrorType.REMOVAL, () => {
|
|
230
|
+
if (!isBrowser() || !navigator.clipboard) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
// Restore original writeText if it was intercepted
|
|
234
|
+
if (this.originalClipboardWriteText) {
|
|
235
|
+
navigator.clipboard.writeText = this.originalClipboardWriteText;
|
|
236
|
+
this.originalClipboardWriteText = null;
|
|
237
|
+
this.log("Restored original clipboard.writeText");
|
|
238
|
+
}
|
|
239
|
+
// Restore original readText if it was intercepted
|
|
240
|
+
if (this.originalClipboardReadText) {
|
|
241
|
+
navigator.clipboard.readText = this.originalClipboardReadText;
|
|
242
|
+
this.originalClipboardReadText = null;
|
|
243
|
+
this.log("Restored original clipboard.readText");
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Intercept document.execCommand to prevent clipboard operations
|
|
249
|
+
*/
|
|
250
|
+
interceptExecCommand() {
|
|
251
|
+
this.safeExecute("interceptExecCommand", StrategyErrorType.APPLICATION, () => {
|
|
252
|
+
if (!isBrowser() || !document.execCommand) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
this.log("Intercepting document.execCommand");
|
|
256
|
+
// Store original execCommand
|
|
257
|
+
this.originalExecCommand = document.execCommand.bind(document);
|
|
258
|
+
// Override execCommand
|
|
259
|
+
document.execCommand = (command, showUI, value) => {
|
|
260
|
+
// Check if this is a clipboard command we want to block
|
|
261
|
+
const lowerCommand = command.toLowerCase();
|
|
262
|
+
if ((lowerCommand === "copy" && this.options.preventCopy) ||
|
|
263
|
+
(lowerCommand === "cut" && this.options.preventCut) ||
|
|
264
|
+
(lowerCommand === "paste" && this.options.preventPaste)) {
|
|
265
|
+
this.log(`document.execCommand('${command}') intercepted`);
|
|
266
|
+
// Call custom handler if provided
|
|
267
|
+
if (this.customHandler) {
|
|
268
|
+
const mockEvent = new ClipboardEvent(lowerCommand);
|
|
269
|
+
this.customHandler(mockEvent, lowerCommand);
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
// For other commands, use the original method
|
|
274
|
+
return this.originalExecCommand(command, showUI, value);
|
|
275
|
+
};
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Restore original document.execCommand
|
|
280
|
+
*/
|
|
281
|
+
restoreExecCommand() {
|
|
282
|
+
this.safeExecute("restoreExecCommand", StrategyErrorType.REMOVAL, () => {
|
|
283
|
+
if (!isBrowser() || !this.originalExecCommand) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
document.execCommand = this.originalExecCommand;
|
|
287
|
+
this.originalExecCommand = null;
|
|
288
|
+
this.log("Restored original document.execCommand");
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ContextMenuOptions, CustomEventHandlers } from "../types";
|
|
2
|
+
import { AbstractStrategy } from "./AbstractStrategy";
|
|
3
|
+
/**
|
|
4
|
+
* Strategy for preventing context menu (right-click)
|
|
5
|
+
*/
|
|
6
|
+
export declare class ContextMenuStrategy extends AbstractStrategy {
|
|
7
|
+
private targetElement;
|
|
8
|
+
private contextMenuHandler;
|
|
9
|
+
private touchStartHandler;
|
|
10
|
+
private touchEndHandler;
|
|
11
|
+
private customHandler?;
|
|
12
|
+
private domObserver;
|
|
13
|
+
private options;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new ContextMenuStrategy
|
|
16
|
+
* @param options Options for customizing the context menu protection
|
|
17
|
+
* @param targetElement Element to protect (defaults to document.body)
|
|
18
|
+
* @param customHandler Optional custom handler for context menu attempts
|
|
19
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
20
|
+
*/
|
|
21
|
+
constructor(options?: ContextMenuOptions, targetElement?: HTMLElement | null, customHandler?: CustomEventHandlers["onContextMenuAttempt"], debugMode?: boolean);
|
|
22
|
+
/**
|
|
23
|
+
* Handle context menu event
|
|
24
|
+
*/
|
|
25
|
+
private handleContextMenu;
|
|
26
|
+
/**
|
|
27
|
+
* Handle touch start event (for mobile)
|
|
28
|
+
*/
|
|
29
|
+
private handleTouchStart;
|
|
30
|
+
/**
|
|
31
|
+
* Handle touch end event (for mobile)
|
|
32
|
+
*/
|
|
33
|
+
private handleTouchEnd;
|
|
34
|
+
/**
|
|
35
|
+
* Set up DOM observer to watch for new iframes
|
|
36
|
+
*/
|
|
37
|
+
private setupIframeObserver;
|
|
38
|
+
/**
|
|
39
|
+
* Protect a specific iframe from context menu
|
|
40
|
+
*/
|
|
41
|
+
private protectIframe;
|
|
42
|
+
/**
|
|
43
|
+
* Find and protect all existing iframes
|
|
44
|
+
*/
|
|
45
|
+
private protectExistingIframes;
|
|
46
|
+
/**
|
|
47
|
+
* Apply context menu protection
|
|
48
|
+
*/
|
|
49
|
+
apply(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Remove context menu protection
|
|
52
|
+
* Override the base implementation to handle the complex removal logic
|
|
53
|
+
*/
|
|
54
|
+
remove(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Update strategy options
|
|
57
|
+
* @param options Options to update
|
|
58
|
+
*/
|
|
59
|
+
updateOptions(options: Partial<ContextMenuOptions> & Record<string, unknown>): void;
|
|
60
|
+
}
|