diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index faca22b9d..4c770f664 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -14,6 +14,8 @@ import type { Options as ObserverOptions } from './observer/top_observer.js' import type { Options as SanitizerOptions } from './sanitizer.js' import type { Options as LoggerOptions } from './logger.js' import type { Options as SessOptions } from './session.js' +import type { Options as NetworkOptions } from '../modules/network.js' + import type { Options as WebworkerOptions, ToWorkerData, @@ -75,6 +77,7 @@ type AppOptions = { // @deprecated onStart?: StartCallback + network?: NetworkOptions } & WebworkerOptions & SessOptions @@ -99,6 +102,7 @@ export default class App { private readonly stopCallbacks: Array<() => any> = [] private readonly commitCallbacks: Array = [] private readonly options: AppOptions + public readonly networkOptions?: NetworkOptions private readonly revID: string private activityState: ActivityState = ActivityState.NotActive private readonly version = 'TRACKER_VERSION' // TODO: version compatability check inside each plugin. @@ -109,6 +113,7 @@ export default class App { // } ?? maybe onStart is good this.projectKey = projectKey + this.networkOptions = options.network this.options = Object.assign( { revID: '', diff --git a/tracker/tracker/src/main/app/observer/iframe_observer.ts b/tracker/tracker/src/main/app/observer/iframe_observer.ts index 05df1fe54..e3b82b1d9 100644 --- a/tracker/tracker/src/main/app/observer/iframe_observer.ts +++ b/tracker/tracker/src/main/app/observer/iframe_observer.ts @@ -1,10 +1,13 @@ import Observer from './observer.js' import { CreateIFrameDocument } from '../messages.gen.js' +import Network from '../../modules/network.js' export default class IFrameObserver extends Observer { observe(iframe: HTMLIFrameElement) { const doc = iframe.contentDocument + const iWindow = iframe.contentWindow const hostID = this.app.nodes.getID(iframe) + console.log(iframe) if (!doc || hostID === undefined) { return } //log TODO common app.logger @@ -16,6 +19,7 @@ export default class IFrameObserver extends Observer { return } this.app.send(CreateIFrameDocument(hostID, docID)) + Network(this.app, this.app.networkOptions, iWindow!) }) } } diff --git a/tracker/tracker/src/main/modules/network.ts b/tracker/tracker/src/main/modules/network.ts index a1a3e2c9c..097648d54 100644 --- a/tracker/tracker/src/main/modules/network.ts +++ b/tracker/tracker/src/main/modules/network.ts @@ -92,7 +92,7 @@ export interface Options { sanitizer?: Sanitizer } -export default function (app: App, opts: Partial = {}) { +export default function (app: App, opts: Partial = {}, customEnv?: Record) { const options: Options = Object.assign( { failuresOnly: false, @@ -150,8 +150,11 @@ export default function (app: App, opts: Partial = {}) { } /* ====== Fetch ====== */ - const origFetch = window.fetch.bind(window) as WindowFetch - window.fetch = (input, init = {}) => { + const origFetch = customEnv + ? (customEnv.fetch.bind(customEnv) as WindowFetch) + : (window.fetch.bind(window) as WindowFetch) + + const trackFetch = (input: RequestInfo | URL, init: RequestInit = {}) => { if (!(typeof input === 'string' || input instanceof URL) || app.isServiceURL(String(input))) { return origFetch(input, init) } @@ -237,12 +240,23 @@ export default function (app: App, opts: Partial = {}) { return response }) } + + if (customEnv) { + customEnv.fetch = trackFetch + } else { + window.fetch = trackFetch + } /* ====== <> ====== */ /* ====== XHR ====== */ - const nativeOpen = XMLHttpRequest.prototype.open - XMLHttpRequest.prototype.open = function (initMethod, url) { - const xhr = this + + const nativeOpen = customEnv + ? customEnv.XMLHttpRequest.prototype.open + : XMLHttpRequest.prototype.open + + function trackXMLHttpReqOpen(initMethod: string, url: string | URL) { + // @ts-ignore ??? this -> XMLHttpRequest + const xhr = this as XMLHttpRequest setSessionTokenHeader((name, value) => xhr.setRequestHeader(name, value)) let startTime = 0 @@ -302,23 +316,47 @@ export default function (app: App, opts: Partial = {}) { //TODO: handle error (though it has no Error API nor any useful information) //xhr.addEventListener('error', (e) => {}) - return nativeOpen.apply(this, arguments) + // @ts-ignore ??? this -> XMLHttpRequest + return nativeOpen.apply(this as XMLHttpRequest, arguments) } + if (customEnv) { + customEnv.XMLHttpRequest.prototype.open = trackXMLHttpReqOpen.bind(customEnv) + } else { + XMLHttpRequest.prototype.open = trackXMLHttpReqOpen + } + const nativeSend = XMLHttpRequest.prototype.send - XMLHttpRequest.prototype.send = function (body) { - const rdo = getXHRRequestDataObject(this) + function trackXHRSend(body: Document | XMLHttpRequestBodyInit | null | undefined) { + // @ts-ignore ??? this -> XMLHttpRequest + const rdo = getXHRRequestDataObject(this as XMLHttpRequest) rdo.body = body - return nativeSend.apply(this, arguments) + // @ts-ignore ??? this -> XMLHttpRequest + return nativeSend.apply(this as XMLHttpRequest, arguments) } + + if (customEnv) { + customEnv.XMLHttpRequest.prototype.send = trackXHRSend.bind(customEnv) + } else { + XMLHttpRequest.prototype.send = trackXHRSend + } + const nativeSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader - XMLHttpRequest.prototype.setRequestHeader = function (name, value) { + + function trackSetReqHeader(name: string, value: string) { if (!isHIgnored(name)) { - const rdo = getXHRRequestDataObject(this) + // @ts-ignore ??? this -> XMLHttpRequest + const rdo = getXHRRequestDataObject(this as XMLHttpRequest) rdo.headers[name] = value } + // @ts-ignore ??? this -> XMLHttpRequest + return nativeSetRequestHeader.apply(this as XMLHttpRequest, arguments) + } - return nativeSetRequestHeader.apply(this, arguments) + if (customEnv) { + customEnv.XMLHttpRequest.prototype.setRequestHeader = trackSetReqHeader.bind(customEnv) + } else { + XMLHttpRequest.prototype.setRequestHeader = trackSetReqHeader } /* ====== <> ====== */ }