@@ -218,7 +218,7 @@ const processWithGlobalScopeExecutionEnv = (
218
218
}
219
219
220
220
/**
221
- * Sandbox that avoids CSP errors, but evaluates everything globally
221
+ * Sandbox that invokes processSignal in the global scope (avoids all CSP errors)
222
222
*/
223
223
interface GlobalScopeSandboxSettings {
224
224
edgeFnDownloadURL : string
@@ -246,35 +246,12 @@ export class NoopSandbox implements SignalSandbox {
246
246
}
247
247
248
248
/**
249
- * window.addEventListener('message', async (event) => {
250
- const { type, payload } = event.data
251
- if (type === 'execute') {
252
- try {
253
- const { signal, signals, analytics, SignalType, EventType, NavigationAction } = payload
254
- await processSignal(signal, { analytics, signals, SignalType, EventType, NavigationAction })
255
- event.source.postMessage({ type: 'result', payload: analytics.getCalls() }, '*')
256
- } catch (err) {
257
- event.source.postMessage({ type: 'error', error: err.message }, '*')
258
- }
259
- }
260
- })
261
-
262
- window.parent.postMessage('iframe_ready', '*')
249
+ * Sandbox that executes code in an iframe.
250
+ * Pros:
251
+ * - More secure
252
+ * Cons:
253
+ * - Can trigger CSP errors unless :blob directive is present
263
254
*/
264
-
265
- const noramizeMethodCallsWithArgResolver = (
266
- methodCalls : AnalyticsMethodCalls
267
- ) => {
268
- const normalizedRuntime = new AnalyticsRuntime ( )
269
- Object . entries ( methodCalls ) . forEach ( ( [ methodName , calls ] ) => {
270
- calls . forEach ( ( args ) => {
271
- // @ts -ignore
272
- normalizedRuntime [ methodName ] ( ...args )
273
- } )
274
- } )
275
- return normalizedRuntime . getCalls ( )
276
- }
277
-
278
255
export class IframeSandbox implements SignalSandbox {
279
256
private iframe : HTMLIFrameElement
280
257
private iframeReady : Promise < void >
@@ -339,7 +316,7 @@ export class IframeSandbox implements SignalSandbox {
339
316
constructor() {
340
317
this.calls = new Map();
341
318
}
342
- getFormattedCalls () {
319
+ getCalls () {
343
320
return Object.fromEntries(this.calls); // call in {track: [args]} format
344
321
}
345
322
createProxy() {
@@ -389,7 +366,7 @@ export class IframeSandbox implements SignalSandbox {
389
366
});
390
367
window.signals.signalBuffer = signalBuffer; // signals is exposed as part of get runtimeCode
391
368
window.processSignal(signal, { signals, constants })
392
- event.source.postMessage({ type: 'execution_result', payload: analyticsProxy.getFormattedCalls () }, '*');
369
+ event.source.postMessage({ type: 'execution_result', payload: analyticsProxy.getCalls () }, '*');
393
370
} catch(err) {
394
371
event.source.postMessage({ type: 'execution_error', error: err }, '*');
395
372
}
@@ -405,6 +382,19 @@ export class IframeSandbox implements SignalSandbox {
405
382
doc . head . appendChild ( runtimeScript )
406
383
}
407
384
385
+ private normalizeAnalyticsMethodCallsWithArgResolver = (
386
+ methodCalls : AnalyticsMethodCalls
387
+ ) => {
388
+ const analytics = new AnalyticsRuntime ( )
389
+ Object . entries ( methodCalls ) . forEach ( ( [ methodName , calls ] ) => {
390
+ calls . forEach ( ( args ) => {
391
+ // @ts -ignore
392
+ analytics [ methodName ] ( ...args )
393
+ } )
394
+ } )
395
+ return analytics . getCalls ( )
396
+ }
397
+
408
398
async execute (
409
399
signal : Signal ,
410
400
signals : Signal [ ]
@@ -416,7 +406,10 @@ export class IframeSandbox implements SignalSandbox {
416
406
if ( e . source !== this . iframe . contentWindow ) return
417
407
if ( e . data ?. type === 'execution_result' ) {
418
408
window . removeEventListener ( 'message' , handler )
419
- resolve ( noramizeMethodCallsWithArgResolver ( e . data . payload ) )
409
+ const methodCalls = this . normalizeAnalyticsMethodCallsWithArgResolver (
410
+ e . data . payload
411
+ )
412
+ resolve ( methodCalls )
420
413
}
421
414
if ( e . data ?. type === 'execution_error' ) {
422
415
window . removeEventListener ( 'message' , handler )
0 commit comments