content-security-toolkit 1.0.1 → 1.0.2
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/README.md +22 -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/index.d.ts +9 -0
- package/dist/core/mediator/handlers/index.js +34 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/otel.d.ts +24 -0
- package/dist/otel.js +87 -0
- package/dist/strategies/AbstractStrategy.mediator.d.ts +162 -0
- package/dist/strategies/AbstractStrategy.mediator.js +349 -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/StrategyRegistry.d.ts +133 -0
- package/dist/strategies/StrategyRegistry.js +379 -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/debuggerDetectionWorker.d.ts +6 -0
- package/dist/utils/detectors/debuggerDetectionWorker.js +24 -0
- package/dist/utils/detectors/firefoxDetector.d.ts +8 -0
- package/dist/utils/detectors/firefoxDetector.js +64 -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/protectedContentManager-simple.d.ts +86 -0
- package/dist/utils/protectedContentManager-simple.js +180 -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/package.json +1 -1
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
import { DomObserver } from "./DOMObserver";
|
|
2
|
+
import { isBrowser } from "./environment";
|
|
3
|
+
import { ProtectionEventType } from "../core/mediator/protection-event";
|
|
4
|
+
/**
|
|
5
|
+
* Utility class to manage security overlays
|
|
6
|
+
*/
|
|
7
|
+
export class SecurityOverlayManager {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new SecurityOverlayManager
|
|
10
|
+
* @param debugMode Enable debug mode for troubleshooting
|
|
11
|
+
*/
|
|
12
|
+
constructor(debugMode = false) {
|
|
13
|
+
this.COMPONENT_NAME = "SecurityOverlayManager";
|
|
14
|
+
this.mediator = null;
|
|
15
|
+
this.overlayElement = null;
|
|
16
|
+
this.eventBlocker = null;
|
|
17
|
+
this.overlayTimeout = null;
|
|
18
|
+
this.domObserver = null;
|
|
19
|
+
this.currentOptions = null;
|
|
20
|
+
this.autoRestoreEnabled = false;
|
|
21
|
+
this.isActive = false;
|
|
22
|
+
// Store references to global event handlers so they can be removed
|
|
23
|
+
this.documentWheelHandler = null;
|
|
24
|
+
this.windowWheelHandler = null;
|
|
25
|
+
this.documentTouchMoveHandler = null;
|
|
26
|
+
this.windowTouchMoveHandler = null;
|
|
27
|
+
// Callbacks
|
|
28
|
+
this.onElementsRemovedCallbacks = [];
|
|
29
|
+
this.debugMode = debugMode;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set the mediator
|
|
33
|
+
* to communicate with the other components
|
|
34
|
+
*/
|
|
35
|
+
setMediator(mediator) {
|
|
36
|
+
this.mediator = mediator;
|
|
37
|
+
// Subscribe only to general overlay events
|
|
38
|
+
this.mediator.subscribe(ProtectionEventType.OVERLAY_SHOWN, this.handleOverlayShown.bind(this), {
|
|
39
|
+
context: this.COMPONENT_NAME,
|
|
40
|
+
});
|
|
41
|
+
this.mediator.subscribe(ProtectionEventType.OVERLAY_REMOVED, this.handleOverlayRemoved.bind(this), {
|
|
42
|
+
context: this.COMPONENT_NAME,
|
|
43
|
+
});
|
|
44
|
+
this.mediator.subscribe(ProtectionEventType.OVERLAY_RESTORED, this.handleOverlayRestored.bind(this), {
|
|
45
|
+
context: this.COMPONENT_NAME,
|
|
46
|
+
});
|
|
47
|
+
if (this.debugMode) {
|
|
48
|
+
console.log("SecurityOverlayManager: Mediator set and subscriptions established");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Handle overlay shown event
|
|
53
|
+
*/
|
|
54
|
+
handleOverlayShown(event) {
|
|
55
|
+
console.log("event received", event);
|
|
56
|
+
try {
|
|
57
|
+
if (this.debugMode) {
|
|
58
|
+
console.log(`SecurityOverlayManager: Received overlay shown event from ${event.source}`, event.data);
|
|
59
|
+
}
|
|
60
|
+
const data = event.data;
|
|
61
|
+
if (!data)
|
|
62
|
+
return;
|
|
63
|
+
// If options are provided directly, use them
|
|
64
|
+
if (data.options) {
|
|
65
|
+
this.showOverlay(data.options);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("SecurityOverlayManager: Error handling overlay shown event", error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle overlay removed event
|
|
74
|
+
*/
|
|
75
|
+
handleOverlayRemoved(event) {
|
|
76
|
+
try {
|
|
77
|
+
if (this.debugMode) {
|
|
78
|
+
console.log(`SecurityOverlayManager: Received overlay removed event from ${event.source}`, event.data);
|
|
79
|
+
}
|
|
80
|
+
this.removeOverlay();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error("SecurityOverlayManager: Error handling overlay removed event", error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handle overlay restored event
|
|
88
|
+
*/
|
|
89
|
+
handleOverlayRestored(event) {
|
|
90
|
+
try {
|
|
91
|
+
if (this.debugMode) {
|
|
92
|
+
console.log(`SecurityOverlayManager: Received overlay restored event from ${event.source}`, event.data);
|
|
93
|
+
}
|
|
94
|
+
this.checkAndRestoreOverlay();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error("SecurityOverlayManager: Error handling overlay restored event", error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Show a security overlay
|
|
102
|
+
* @param options Options for the overlay
|
|
103
|
+
* @returns Object containing the created overlay and event blocker elements
|
|
104
|
+
*/
|
|
105
|
+
showOverlay(options) {
|
|
106
|
+
if (!isBrowser()) {
|
|
107
|
+
return { overlay: null, blocker: null };
|
|
108
|
+
}
|
|
109
|
+
// Store current options for potential restoration
|
|
110
|
+
this.currentOptions = { ...options };
|
|
111
|
+
// Set auto-restore flag
|
|
112
|
+
this.autoRestoreEnabled = options.autoRestore !== false; // Default to true if not specified
|
|
113
|
+
this.isActive = true;
|
|
114
|
+
// Remove any existing overlay first
|
|
115
|
+
this.removeOverlay(false); // Pass false to prevent disabling autoRestore
|
|
116
|
+
// Create event blocker if requested
|
|
117
|
+
if (options.blockEvents) {
|
|
118
|
+
this.eventBlocker = this.createEventBlocker();
|
|
119
|
+
document.body.appendChild(this.eventBlocker);
|
|
120
|
+
if (this.debugMode) {
|
|
121
|
+
console.log("SecurityOverlayManager: Event blocker created and added to DOM");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Create the overlay
|
|
125
|
+
this.overlayElement = this.createOverlay(options);
|
|
126
|
+
document.body.appendChild(this.overlayElement);
|
|
127
|
+
if (this.debugMode) {
|
|
128
|
+
console.log("SecurityOverlayManager: Overlay created and added to DOM");
|
|
129
|
+
}
|
|
130
|
+
// Set up timeout if duration is specified
|
|
131
|
+
if (options.duration && options.duration > 0) {
|
|
132
|
+
this.overlayTimeout = window.setTimeout(() => {
|
|
133
|
+
this.removeOverlay();
|
|
134
|
+
this.overlayTimeout = null;
|
|
135
|
+
}, options.duration);
|
|
136
|
+
if (this.debugMode) {
|
|
137
|
+
console.log(`SecurityOverlayManager: Overlay will auto-remove after ${options.duration}ms`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Set up observer for auto-restoration if enabled
|
|
141
|
+
if (this.autoRestoreEnabled) {
|
|
142
|
+
this.setupObserver();
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
overlay: this.overlayElement,
|
|
146
|
+
blocker: this.eventBlocker,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Remove the security overlay and clean up all event listeners
|
|
151
|
+
* @param disableAutoRestore Whether to disable auto-restoration when removing
|
|
152
|
+
*/
|
|
153
|
+
removeOverlay(disableAutoRestore = true) {
|
|
154
|
+
if (!isBrowser())
|
|
155
|
+
return;
|
|
156
|
+
// Clear any existing timeout
|
|
157
|
+
if (this.overlayTimeout !== null) {
|
|
158
|
+
window.clearTimeout(this.overlayTimeout);
|
|
159
|
+
this.overlayTimeout = null;
|
|
160
|
+
}
|
|
161
|
+
// Stop observer if it exists and if disableAutoRestore is true
|
|
162
|
+
if (disableAutoRestore && this.domObserver) {
|
|
163
|
+
this.domObserver.stopObserving();
|
|
164
|
+
this.domObserver = null;
|
|
165
|
+
}
|
|
166
|
+
// Remove overlay
|
|
167
|
+
if (this.overlayElement && this.overlayElement.parentNode) {
|
|
168
|
+
this.overlayElement.parentNode.removeChild(this.overlayElement);
|
|
169
|
+
this.overlayElement = null;
|
|
170
|
+
if (this.debugMode) {
|
|
171
|
+
console.log("SecurityOverlayManager: Overlay removed from DOM");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Remove event blocker
|
|
175
|
+
if (this.eventBlocker && this.eventBlocker.parentNode) {
|
|
176
|
+
this.eventBlocker.parentNode.removeChild(this.eventBlocker);
|
|
177
|
+
this.eventBlocker = null;
|
|
178
|
+
if (this.debugMode) {
|
|
179
|
+
console.log("SecurityOverlayManager: Event blocker removed from DOM");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Also try to remove by ID in case references were lost
|
|
183
|
+
const overlayById = document.getElementById("security-overlay");
|
|
184
|
+
if (overlayById && overlayById.parentNode) {
|
|
185
|
+
overlayById.parentNode.removeChild(overlayById);
|
|
186
|
+
}
|
|
187
|
+
const blockerById = document.getElementById("security-event-blocker");
|
|
188
|
+
if (blockerById && blockerById.parentNode) {
|
|
189
|
+
blockerById.parentNode.removeChild(blockerById);
|
|
190
|
+
}
|
|
191
|
+
// Remove global event listeners
|
|
192
|
+
this.removeGlobalEventListeners();
|
|
193
|
+
// Clear current options and set isActive to false when intentionally removing the overlay
|
|
194
|
+
if (disableAutoRestore) {
|
|
195
|
+
this.currentOptions = null;
|
|
196
|
+
this.autoRestoreEnabled = false;
|
|
197
|
+
this.isActive = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Disable auto-restoration of the overlay
|
|
202
|
+
* This should be called when the condition that triggered the overlay is no longer true
|
|
203
|
+
*/
|
|
204
|
+
disableAutoRestore() {
|
|
205
|
+
this.autoRestoreEnabled = false;
|
|
206
|
+
if (this.domObserver) {
|
|
207
|
+
this.domObserver.stopObserving();
|
|
208
|
+
this.domObserver = null;
|
|
209
|
+
}
|
|
210
|
+
if (this.debugMode) {
|
|
211
|
+
console.log("SecurityOverlayManager: Auto-restore disabled");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Check if the manager is active
|
|
216
|
+
* This returns true if the overlay is supposed to be shown, regardless of whether it's currently
|
|
217
|
+
* in the DOM or has been removed by external forces
|
|
218
|
+
*/
|
|
219
|
+
isOverlayActive() {
|
|
220
|
+
return this.isActive;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Ensure the overlay is restored if it should be active but isn't displayed
|
|
224
|
+
* This is useful for external components to check if the overlay should be restored
|
|
225
|
+
*/
|
|
226
|
+
checkAndRestoreOverlay() {
|
|
227
|
+
if (this.isActive && this.autoRestoreEnabled && this.currentOptions && !this.doesOverlayExistInDOM()) {
|
|
228
|
+
if (this.debugMode) {
|
|
229
|
+
console.log("SecurityOverlayManager: Overlay missing from DOM but should be active, restoring...");
|
|
230
|
+
}
|
|
231
|
+
this.showOverlay(this.currentOptions);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Remove global event listeners that were added to document and window
|
|
236
|
+
*/
|
|
237
|
+
removeGlobalEventListeners() {
|
|
238
|
+
if (!isBrowser())
|
|
239
|
+
return;
|
|
240
|
+
// Remove document wheel handler
|
|
241
|
+
if (this.documentWheelHandler) {
|
|
242
|
+
document.removeEventListener("wheel", this.documentWheelHandler, { capture: true });
|
|
243
|
+
this.documentWheelHandler = null;
|
|
244
|
+
if (this.debugMode) {
|
|
245
|
+
console.log("SecurityOverlayManager: Removed document wheel event listener");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Remove window wheel handler
|
|
249
|
+
if (this.windowWheelHandler) {
|
|
250
|
+
window.removeEventListener("wheel", this.windowWheelHandler, { capture: true });
|
|
251
|
+
this.windowWheelHandler = null;
|
|
252
|
+
if (this.debugMode) {
|
|
253
|
+
console.log("SecurityOverlayManager: Removed window wheel event listener");
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Remove document touchmove handler
|
|
257
|
+
if (this.documentTouchMoveHandler) {
|
|
258
|
+
document.removeEventListener("touchmove", this.documentTouchMoveHandler, { capture: true });
|
|
259
|
+
this.documentTouchMoveHandler = null;
|
|
260
|
+
if (this.debugMode) {
|
|
261
|
+
console.log("SecurityOverlayManager: Removed document touchmove event listener");
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Remove window touchmove handler
|
|
265
|
+
if (this.windowTouchMoveHandler) {
|
|
266
|
+
window.removeEventListener("touchmove", this.windowTouchMoveHandler, { capture: true });
|
|
267
|
+
this.windowTouchMoveHandler = null;
|
|
268
|
+
if (this.debugMode) {
|
|
269
|
+
console.log("SecurityOverlayManager: Removed window touchmove event listener");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Re-enable scrolling on body
|
|
273
|
+
if (document.body) {
|
|
274
|
+
document.body.style.overflow = "";
|
|
275
|
+
document.body.style.position = "";
|
|
276
|
+
document.body.style.height = "";
|
|
277
|
+
document.body.style.width = "";
|
|
278
|
+
document.body.style.top = "";
|
|
279
|
+
document.body.style.left = "";
|
|
280
|
+
if (this.debugMode) {
|
|
281
|
+
console.log("SecurityOverlayManager: Re-enabled scrolling on body");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// Re-enable scrolling on html
|
|
285
|
+
const htmlElement = document.documentElement;
|
|
286
|
+
if (htmlElement) {
|
|
287
|
+
htmlElement.style.overflow = "";
|
|
288
|
+
if (this.debugMode) {
|
|
289
|
+
console.log("SecurityOverlayManager: Re-enabled scrolling on html");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Create an overlay element
|
|
295
|
+
* @param options Options for the overlay
|
|
296
|
+
* @returns The created overlay element
|
|
297
|
+
*/
|
|
298
|
+
createOverlay(options) {
|
|
299
|
+
if (!isBrowser()) {
|
|
300
|
+
throw new Error("Document is not available");
|
|
301
|
+
}
|
|
302
|
+
// Create overlay element
|
|
303
|
+
const overlay = document.createElement("div");
|
|
304
|
+
overlay.id = "security-overlay";
|
|
305
|
+
// Apply styles
|
|
306
|
+
const styles = {
|
|
307
|
+
position: "fixed",
|
|
308
|
+
top: "0",
|
|
309
|
+
left: "0",
|
|
310
|
+
width: "100%",
|
|
311
|
+
height: "100%",
|
|
312
|
+
backgroundColor: options.backgroundColor || "rgba(220, 38, 38, 0.9)",
|
|
313
|
+
zIndex: options.zIndex || "2147483647",
|
|
314
|
+
display: "flex",
|
|
315
|
+
flexDirection: "column",
|
|
316
|
+
justifyContent: "center",
|
|
317
|
+
alignItems: "center",
|
|
318
|
+
fontFamily: "sans-serif",
|
|
319
|
+
color: options.textColor || "white",
|
|
320
|
+
padding: "20px",
|
|
321
|
+
textAlign: "center",
|
|
322
|
+
pointerEvents: "auto", // Always allow interaction with the overlay itself
|
|
323
|
+
...options.customStyles,
|
|
324
|
+
};
|
|
325
|
+
// Apply styles to the overlay
|
|
326
|
+
Object.entries(styles).forEach(([key, value]) => {
|
|
327
|
+
if (value !== undefined) {
|
|
328
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
329
|
+
;
|
|
330
|
+
overlay.style[key] = value;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
// Create HTML content
|
|
334
|
+
let content = "";
|
|
335
|
+
if (options.title) {
|
|
336
|
+
content += `<h2 style="font-size: 24px; margin-bottom: 20px;">${options.title}</h2>`;
|
|
337
|
+
}
|
|
338
|
+
if (options.message) {
|
|
339
|
+
content += `<p style="font-size: 16px; margin-bottom: 10px;">${options.message}</p>`;
|
|
340
|
+
}
|
|
341
|
+
if (options.secondaryMessage) {
|
|
342
|
+
content += `<p style="font-size: 16px; margin-top: 10px;">${options.secondaryMessage}</p>`;
|
|
343
|
+
}
|
|
344
|
+
if (options.additionalContent) {
|
|
345
|
+
content += options.additionalContent;
|
|
346
|
+
}
|
|
347
|
+
if (options.showCloseButton) {
|
|
348
|
+
content += `
|
|
349
|
+
<button id="security-overlay-close" style="margin-top: 20px; padding: 10px 20px; background-color: white; color: black; border: none; border-radius: 4px; cursor: pointer; pointer-events: auto;">
|
|
350
|
+
${options.closeButtonText || "Close"}
|
|
351
|
+
</button>
|
|
352
|
+
`;
|
|
353
|
+
}
|
|
354
|
+
overlay.innerHTML = content;
|
|
355
|
+
// Add event listener to close button if present
|
|
356
|
+
if (options.showCloseButton) {
|
|
357
|
+
setTimeout(() => {
|
|
358
|
+
const closeButton = document.getElementById("security-overlay-close");
|
|
359
|
+
if (closeButton) {
|
|
360
|
+
closeButton.addEventListener("click", () => {
|
|
361
|
+
if (options.onCloseButtonClick) {
|
|
362
|
+
options.onCloseButtonClick();
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
this.removeOverlay();
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}, 0);
|
|
370
|
+
}
|
|
371
|
+
return overlay;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Create an event blocker that prevents interaction with the page
|
|
375
|
+
* @returns The created event blocker element
|
|
376
|
+
*/
|
|
377
|
+
createEventBlocker() {
|
|
378
|
+
const blocker = document.createElement("div");
|
|
379
|
+
blocker.id = "security-event-blocker";
|
|
380
|
+
// Apply styles to make it cover the entire page and block all events
|
|
381
|
+
blocker.style.position = "fixed";
|
|
382
|
+
blocker.style.top = "0";
|
|
383
|
+
blocker.style.left = "0";
|
|
384
|
+
blocker.style.width = "100%";
|
|
385
|
+
blocker.style.height = "100%";
|
|
386
|
+
blocker.style.backgroundColor = "transparent"; // Transparent but will block events
|
|
387
|
+
blocker.style.zIndex = "2147483646"; // Just below the overlay
|
|
388
|
+
blocker.style.cursor = "not-allowed"; // Show not-allowed cursor
|
|
389
|
+
// Add event listeners to block all interactions
|
|
390
|
+
const blockEvent = (e) => {
|
|
391
|
+
e.preventDefault();
|
|
392
|
+
e.stopPropagation();
|
|
393
|
+
return false;
|
|
394
|
+
};
|
|
395
|
+
// Block all common events
|
|
396
|
+
const events = [
|
|
397
|
+
"click",
|
|
398
|
+
"dblclick",
|
|
399
|
+
"mousedown",
|
|
400
|
+
"mouseup",
|
|
401
|
+
"mousemove",
|
|
402
|
+
"touchstart",
|
|
403
|
+
"touchend",
|
|
404
|
+
"touchmove",
|
|
405
|
+
"touchcancel",
|
|
406
|
+
"keydown",
|
|
407
|
+
"keyup",
|
|
408
|
+
"keypress",
|
|
409
|
+
"contextmenu",
|
|
410
|
+
"selectstart",
|
|
411
|
+
"dragstart",
|
|
412
|
+
"wheel", // Add wheel event to block scrolling
|
|
413
|
+
"scroll", // Add scroll event as well
|
|
414
|
+
];
|
|
415
|
+
events.forEach((eventType) => {
|
|
416
|
+
blocker.addEventListener(eventType, blockEvent, { capture: true, passive: false });
|
|
417
|
+
});
|
|
418
|
+
// Additional handling for wheel events on document and window
|
|
419
|
+
if (isBrowser()) {
|
|
420
|
+
// Store references to handlers so they can be removed later
|
|
421
|
+
this.documentWheelHandler = blockEvent;
|
|
422
|
+
this.windowWheelHandler = blockEvent;
|
|
423
|
+
this.documentTouchMoveHandler = blockEvent;
|
|
424
|
+
this.windowTouchMoveHandler = blockEvent;
|
|
425
|
+
// Prevent scrolling on the document and window level
|
|
426
|
+
document.addEventListener("wheel", this.documentWheelHandler, { capture: true, passive: false });
|
|
427
|
+
window.addEventListener("wheel", this.windowWheelHandler, { capture: true, passive: false });
|
|
428
|
+
// Also prevent scrolling via touch on mobile
|
|
429
|
+
document.addEventListener("touchmove", this.documentTouchMoveHandler, { capture: true, passive: false });
|
|
430
|
+
window.addEventListener("touchmove", this.windowTouchMoveHandler, { capture: true, passive: false });
|
|
431
|
+
if (this.debugMode) {
|
|
432
|
+
console.log("SecurityOverlayManager: Added global event listeners to prevent scrolling");
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return blocker;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Set up DOM observer to detect when overlay elements are removed
|
|
439
|
+
*/
|
|
440
|
+
setupObserver() {
|
|
441
|
+
if (!isBrowser())
|
|
442
|
+
return;
|
|
443
|
+
const elementsToWatch = [];
|
|
444
|
+
if (this.overlayElement) {
|
|
445
|
+
elementsToWatch.push(this.overlayElement);
|
|
446
|
+
}
|
|
447
|
+
if (this.eventBlocker) {
|
|
448
|
+
elementsToWatch.push(this.eventBlocker);
|
|
449
|
+
}
|
|
450
|
+
if (elementsToWatch.length === 0)
|
|
451
|
+
return;
|
|
452
|
+
// Create a handler for element removal
|
|
453
|
+
const handleElementsRemoved = (removedElements) => {
|
|
454
|
+
if (this.debugMode) {
|
|
455
|
+
console.log("SecurityOverlayManager: Overlay elements removed from DOM", removedElements);
|
|
456
|
+
}
|
|
457
|
+
// Only restore if auto-restore is enabled
|
|
458
|
+
if (this.autoRestoreEnabled && this.currentOptions && this.isActive) {
|
|
459
|
+
if (this.debugMode) {
|
|
460
|
+
console.log("SecurityOverlayManager: Auto-restoring overlay");
|
|
461
|
+
}
|
|
462
|
+
// Restore the overlay with the same options
|
|
463
|
+
this.showOverlay(this.currentOptions);
|
|
464
|
+
// Notify callbacks
|
|
465
|
+
this.notifyElementsRemovedCallbacks(removedElements);
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
// Stop any existing observer
|
|
469
|
+
if (this.domObserver) {
|
|
470
|
+
this.domObserver.stopObserving();
|
|
471
|
+
}
|
|
472
|
+
this.domObserver = new DomObserver({
|
|
473
|
+
targetElement: document.body,
|
|
474
|
+
elementsToWatch,
|
|
475
|
+
onElementsRemoved: handleElementsRemoved,
|
|
476
|
+
observeSubtree: true,
|
|
477
|
+
debugMode: this.debugMode,
|
|
478
|
+
name: "SecurityOverlayManager",
|
|
479
|
+
});
|
|
480
|
+
this.domObserver.startObserving();
|
|
481
|
+
if (this.debugMode) {
|
|
482
|
+
console.log("SecurityOverlayManager: DOM observer set up");
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Notify all callbacks when elements are removed
|
|
487
|
+
*/
|
|
488
|
+
notifyElementsRemovedCallbacks(removedElements) {
|
|
489
|
+
for (const callback of this.onElementsRemovedCallbacks) {
|
|
490
|
+
try {
|
|
491
|
+
callback(removedElements);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
console.error("SecurityOverlayManager: Error in elements removed callback:", error);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Add a callback to be called when overlay elements are removed
|
|
500
|
+
* @param callback Callback function
|
|
501
|
+
*/
|
|
502
|
+
addElementsRemovedCallback(callback) {
|
|
503
|
+
this.onElementsRemovedCallbacks.push(callback);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Remove a callback
|
|
507
|
+
* @param callback Callback function to remove
|
|
508
|
+
*/
|
|
509
|
+
removeElementsRemovedCallback(callback) {
|
|
510
|
+
this.onElementsRemovedCallbacks = this.onElementsRemovedCallbacks.filter((cb) => cb !== callback);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Check if an overlay is currently displayed
|
|
514
|
+
* @returns True if an overlay is displayed, false otherwise
|
|
515
|
+
*/
|
|
516
|
+
isOverlayDisplayed() {
|
|
517
|
+
return this.overlayElement !== null;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Get the current overlay element
|
|
521
|
+
* @returns The current overlay element or null if none exists
|
|
522
|
+
*/
|
|
523
|
+
getOverlayElement() {
|
|
524
|
+
return this.overlayElement;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Get the current event blocker element
|
|
528
|
+
* @returns The current event blocker element or null if none exists
|
|
529
|
+
*/
|
|
530
|
+
getEventBlocker() {
|
|
531
|
+
return this.eventBlocker;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Check if the overlay exists in the DOM
|
|
535
|
+
* This is different from isOverlayDisplayed() which checks if the manager has a reference
|
|
536
|
+
* @returns True if the overlay exists in the DOM, false otherwise
|
|
537
|
+
*/
|
|
538
|
+
doesOverlayExistInDOM() {
|
|
539
|
+
if (!isBrowser())
|
|
540
|
+
return false;
|
|
541
|
+
const overlayInDOM = document.getElementById("security-overlay") !== null;
|
|
542
|
+
const blockerInDOM = document.getElementById("security-event-blocker") !== null;
|
|
543
|
+
// If we have a reference but the element isn't in the DOM, update our reference
|
|
544
|
+
if (this.overlayElement && !overlayInDOM) {
|
|
545
|
+
this.overlayElement = null;
|
|
546
|
+
}
|
|
547
|
+
if (this.eventBlocker && !blockerInDOM) {
|
|
548
|
+
this.eventBlocker = null;
|
|
549
|
+
}
|
|
550
|
+
return overlayInDOM || blockerInDOM;
|
|
551
|
+
}
|
|
552
|
+
}
|