@openreplay/tracker 3.3.0 → 3.4.1

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.
@@ -15,8 +15,10 @@ export declare type Options = {
15
15
  session_pageno_key: string;
16
16
  local_uuid_key: string;
17
17
  ingestPoint: string;
18
+ resourceBaseHref: string | null;
18
19
  __is_snippet: boolean;
19
20
  __debug_report_edp: string | null;
21
+ __debug_log: boolean;
20
22
  onStart?: (info: OnStartInfo) => void;
21
23
  } & ObserverOptions & WebworkerOptions;
22
24
  declare type Callback = () => void;
@@ -38,7 +40,7 @@ export default class App {
38
40
  private version;
39
41
  private readonly worker?;
40
42
  constructor(projectKey: string, sessionToken: string | null | undefined, opts: Partial<Options>);
41
- private sendDebugReport;
43
+ private _debug;
42
44
  send(message: Message, urgent?: boolean): void;
43
45
  private commit;
44
46
  addCommitCallback(cb: CommitCallback): void;
@@ -49,6 +51,9 @@ export default class App {
49
51
  getSessionToken(): string | undefined;
50
52
  getSessionID(): string | undefined;
51
53
  getHost(): string;
54
+ getProjectKey(): string;
55
+ getBaseHref(): string;
56
+ resolveResourceURL(resourceURL: string): string;
52
57
  isServiceURL(url: string): boolean;
53
58
  active(): boolean;
54
59
  private _start;
package/cjs/app/index.js CHANGED
@@ -17,7 +17,7 @@ class App {
17
17
  this.commitCallbacks = [];
18
18
  this._sessionID = null;
19
19
  this.isActive = false;
20
- this.version = '3.3.0';
20
+ this.version = '3.4.1';
21
21
  this.projectKey = projectKey;
22
22
  this.options = Object.assign({
23
23
  revID: '',
@@ -26,10 +26,13 @@ class App {
26
26
  session_pageno_key: '__openreplay_pageno',
27
27
  local_uuid_key: '__openreplay_uuid',
28
28
  ingestPoint: exports.DEFAULT_INGEST_POINT,
29
+ resourceBaseHref: null,
29
30
  __is_snippet: false,
30
31
  __debug_report_edp: null,
32
+ __debug_log: false,
31
33
  obscureTextEmails: true,
32
34
  obscureTextNumbers: false,
35
+ captureIFrames: false,
33
36
  }, opts);
34
37
  if (sessionToken != null) {
35
38
  sessionStorage.setItem(this.options.session_token_key, sessionToken);
@@ -40,12 +43,11 @@ class App {
40
43
  this.ticker = new ticker_1.default(this);
41
44
  this.ticker.attach(() => this.commit());
42
45
  try {
43
- this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const k=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,k);const E=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,E);const z=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,z);const w=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,w);const I=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,I);const L=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,L);const T=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,T);const C=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,C);const A=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,A);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const U=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,U);const N=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,N);const O=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,O);const q=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,q);const D=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,D);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const K=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,K);const G=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,G);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class Z{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for(;t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=Y.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let tt,st=1e6,it=4e5,nt=new Z(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}const lt=[];let gt,ft=!1,pt=0,mt=8e3,_t=10;function yt(){if(at||""===rt||""===et)return;const t=nt.flush();ft?lt.push(t):(ft=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return vt(),lt.length=0,403===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=lt.shift();s?t(s):ft=!1}},i.onerror=function(i){if(pt>=_t)return vt(),void self.postMessage(null);pt++,setTimeout(()=>t(s),mt)},i.send(s.buffer)}(t)),at=!0,dt()}function vt(){et="",rt="",clearInterval(tt),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(yt(),void vt()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?gt=setTimeout(()=>self.postMessage("restart"),3e5):clearTimeout(gt)),nt.checkpoint(),!i.encode(nt)&&(yt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new Z(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,_t=t.connAttemptCount||_t,mt=t.connAttemptGap||mt,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null==tt&&(tt=setInterval(yt,2e4))));yt()};
46
+ this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st,it=1e6,nt=4e5,et=new tt(nt),rt="",ot="",ht=0,ct=0,ut=0,at=0,dt=!0;function lt(){return new i(ht,at,ct).encode(et)}const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(dt||""===ot||""===rt)return;const t=et.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",rt+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+ot),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),dt=!0,lt()}function St(){rt="",ot="",clearInterval(st),et.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ct=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),3e5):clearTimeout(ft)),et.checkpoint(),!i.encode(et)&&(vt(),!i.encode(et)))for(;!i.encode(et);){if(nt===it)return console.warn("OpenReplay: beacon size overflow."),et.reset(),void lt();nt=Math.min(2*nt,it),et=new tt(nt),lt()}at++,dt=!1}):(rt=t.ingestPoint||rt,ot=t.token||ot,ht=t.pageNo||ht,ct=t.startTimestamp||ct,ut=t.timeAdjustment||ut,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,it=t.beaconSizeLimit||it,nt=Math.min(it,t.beaconSize||nt),et.isEmpty()&&lt(),void(null==st&&(st=setInterval(vt,2e4))));vt()};
44
47
  `], { type: 'text/javascript' })));
45
- // this.worker.onerror = e => {
46
- // this.send(new TechnicalInfo("webworker_error", JSON.stringify(e)));
47
- // /* TODO: send report */
48
- // }
48
+ this.worker.onerror = e => {
49
+ this._debug("webworker_error", e);
50
+ };
49
51
  let lastTs = utils_1.timestamp();
50
52
  let fileno = 0;
51
53
  this.worker.onmessage = ({ data }) => {
@@ -62,25 +64,30 @@ class App {
62
64
  this.worker.postMessage(null);
63
65
  }
64
66
  };
67
+ // TODO:on start
65
68
  // TODO: keep better tactics, discard others (look https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon)
66
69
  this.attachEventListener(window, 'beforeunload', alertWorker, false);
67
70
  this.attachEventListener(document, 'mouseleave', alertWorker, false, false);
68
71
  this.attachEventListener(document, 'visibilitychange', alertWorker, false);
69
72
  }
70
73
  catch (e) {
71
- this.sendDebugReport("worker_start", e);
74
+ this._debug("worker_start", e);
72
75
  }
73
76
  }
74
- sendDebugReport(context, e) {
77
+ _debug(context, e) {
75
78
  if (this.options.__debug_report_edp !== null) {
76
79
  fetch(this.options.__debug_report_edp, {
77
80
  method: 'POST',
81
+ headers: { 'Content-Type': 'application/json' },
78
82
  body: JSON.stringify({
79
83
  context,
80
84
  error: `${e}`
81
85
  })
82
86
  });
83
87
  }
88
+ if (this.options.__debug_log) {
89
+ utils_1.warn("OpenReplay errror: ", context, e);
90
+ }
84
91
  }
85
92
  send(message, urgent = false) {
86
93
  if (!this.isActive) {
@@ -109,12 +116,11 @@ class App {
109
116
  fn.apply(this, args);
110
117
  }
111
118
  catch (e) {
112
- app.send(new messages_1.TechnicalInfo("error", JSON.stringify({
113
- time: utils_1.timestamp(),
114
- name: e.name,
115
- message: e.message,
116
- stack: e.stack
117
- })));
119
+ this._debug("safe_fn_call", e);
120
+ // time: timestamp(),
121
+ // name: e.name,
122
+ // message: e.message,
123
+ // stack: e.stack
118
124
  }
119
125
  }; // TODO: correct typing
120
126
  }
@@ -141,7 +147,30 @@ class App {
141
147
  return this._sessionID || undefined;
142
148
  }
143
149
  getHost() {
144
- return new URL(this.options.ingestPoint).host;
150
+ return new URL(this.options.ingestPoint).hostname;
151
+ }
152
+ getProjectKey() {
153
+ return this.projectKey;
154
+ }
155
+ getBaseHref() {
156
+ var _a, _b;
157
+ if (typeof this.options.resourceBaseHref === 'string') {
158
+ return this.options.resourceBaseHref;
159
+ }
160
+ else if (typeof this.options.resourceBaseHref === 'object') {
161
+ //switch between types
162
+ }
163
+ if (document.baseURI) {
164
+ return document.baseURI;
165
+ }
166
+ // IE only
167
+ return ((_b = (_a = document.head) === null || _a === void 0 ? void 0 : _a.getElementsByTagName("base")[0]) === null || _b === void 0 ? void 0 : _b.getAttribute("href")) || location.origin + location.pathname;
168
+ }
169
+ resolveResourceURL(resourceURL) {
170
+ const base = new URL(this.getBaseHref());
171
+ base.pathname += "/" + new URL(resourceURL).pathname;
172
+ base.pathname.replace(/\/+/g, "/");
173
+ return base.toString();
145
174
  }
146
175
  isServiceURL(url) {
147
176
  return url.startsWith(this.options.ingestPoint);
@@ -151,10 +180,10 @@ class App {
151
180
  }
152
181
  _start(reset) {
153
182
  if (!this.isActive) {
154
- this.isActive = true;
155
183
  if (!this.worker) {
156
- throw new Error("Stranger things: no worker found");
184
+ return Promise.reject("No worker found: perhaps, CSP is not set.");
157
185
  }
186
+ this.isActive = true;
158
187
  let pageNo = 0;
159
188
  const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
160
189
  if (pageNoStr != null) {
@@ -212,7 +241,7 @@ class App {
212
241
  this._sessionID = sessionID;
213
242
  }
214
243
  if (!this.worker) {
215
- throw new Error("Stranger things: no worker found after start request");
244
+ throw new Error("no worker found after start request (this might not happen)");
216
245
  }
217
246
  this.worker.postMessage({ token, beaconSizeLimit });
218
247
  this.startCallbacks.forEach((cb) => cb());
@@ -227,7 +256,8 @@ class App {
227
256
  })
228
257
  .catch(e => {
229
258
  this.stop();
230
- this.sendDebugReport("session_start", e);
259
+ utils_1.warn("OpenReplay was unable to start. ", e);
260
+ this._debug("session_start", e);
231
261
  throw e;
232
262
  });
233
263
  }
@@ -1,10 +1,22 @@
1
1
  import App from './index';
2
+ interface Window extends WindowProxy {
3
+ HTMLInputElement: typeof HTMLInputElement;
4
+ HTMLLinkElement: typeof HTMLLinkElement;
5
+ HTMLStyleElement: typeof HTMLStyleElement;
6
+ SVGStyleElement: typeof SVGStyleElement;
7
+ HTMLIFrameElement: typeof HTMLIFrameElement;
8
+ Text: typeof Text;
9
+ Element: typeof Element;
10
+ }
2
11
  export interface Options {
3
12
  obscureTextEmails: boolean;
4
13
  obscureTextNumbers: boolean;
14
+ captureIFrames: boolean;
5
15
  }
6
16
  export default class Observer {
7
17
  private readonly app;
18
+ private readonly options;
19
+ private readonly context;
8
20
  private readonly observer;
9
21
  private readonly commited;
10
22
  private readonly recents;
@@ -12,9 +24,10 @@ export default class Observer {
12
24
  private readonly attributesList;
13
25
  private readonly textSet;
14
26
  private readonly textMasked;
15
- private readonly options;
16
- constructor(app: App, opts: Options);
27
+ constructor(app: App, options: Options, context?: Window);
17
28
  private clear;
29
+ private isInstance;
30
+ private isIgnored;
18
31
  private sendNodeAttribute;
19
32
  private sendNodeData;
20
33
  private bindNode;
@@ -23,6 +36,10 @@ export default class Observer {
23
36
  private _commitNode;
24
37
  private commitNode;
25
38
  private commitNodes;
39
+ private iframeObservers;
40
+ private handleIframe;
41
+ private observeIframe;
26
42
  observe(): void;
27
43
  disconnect(): void;
28
44
  }
45
+ export {};
@@ -5,36 +5,40 @@ const messages_1 = require("../messages");
5
5
  function isSVGElement(node) {
6
6
  return node.namespaceURI === 'http://www.w3.org/2000/svg';
7
7
  }
8
- function isIgnored(node) {
9
- if (node instanceof Text) {
10
- return false;
11
- }
12
- if (!(node instanceof Element)) {
13
- return true;
14
- }
15
- const tag = node.tagName.toUpperCase();
16
- if (tag === 'LINK') {
17
- const rel = node.getAttribute('rel');
18
- const as = node.getAttribute('as');
19
- return !((rel === null || rel === void 0 ? void 0 : rel.includes('stylesheet')) || as === "style" || as === "font");
20
- }
21
- return (tag === 'SCRIPT' ||
22
- tag === 'NOSCRIPT' ||
23
- tag === 'META' ||
24
- tag === 'TITLE' ||
25
- tag === 'BASE');
26
- }
27
8
  class Observer {
28
- constructor(app, opts) {
9
+ constructor(app, options, context = window) {
29
10
  this.app = app;
30
- this.options = opts;
11
+ this.options = options;
12
+ this.context = context;
13
+ this.iframeObservers = [];
31
14
  this.observer = new MutationObserver(this.app.safe((mutations) => {
15
+ var _a;
32
16
  for (const mutation of mutations) {
33
17
  const target = mutation.target;
34
- if (isIgnored(target) || !document.contains(target)) {
18
+ const type = mutation.type;
19
+ // Special case
20
+ // Document 'childList' might happen in case of iframe.
21
+ // TODO: generalize as much as possible
22
+ if (this.isInstance(target, Document)
23
+ && type === 'childList'
24
+ //&& new Array(mutation.addedNodes).some(node => this.isInstance(node, HTMLHtmlElement))
25
+ ) {
26
+ const parentFrame = (_a = target.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement;
27
+ if (!parentFrame) {
28
+ continue;
29
+ }
30
+ this.bindTree(target.documentElement);
31
+ const frameID = this.app.nodes.getID(parentFrame);
32
+ const docID = this.app.nodes.getID(target.documentElement);
33
+ if (frameID === undefined || docID === undefined) {
34
+ continue;
35
+ }
36
+ this.app.send(messages_1.CreateIFrameDocument(frameID, docID));
37
+ continue;
38
+ }
39
+ if (this.isIgnored(target) || !context.document.contains(target)) {
35
40
  continue;
36
41
  }
37
- const type = mutation.type;
38
42
  if (type === 'childList') {
39
43
  for (let i = 0; i < mutation.removedNodes.length; i++) {
40
44
  this.bindTree(mutation.removedNodes[i]);
@@ -85,6 +89,39 @@ class Observer {
85
89
  this.textSet.clear();
86
90
  this.textMasked.clear();
87
91
  }
92
+ // TODO: we need a type expert here so we won't have to ignore the lines
93
+ isInstance(node, constr) {
94
+ let context = this.context;
95
+ while (context.parent && context.parent !== context) {
96
+ // @ts-ignore
97
+ if (node instanceof context[constr.name]) {
98
+ return true;
99
+ }
100
+ // @ts-ignore
101
+ context = context.parent;
102
+ }
103
+ // @ts-ignore
104
+ return node instanceof context[constr.name];
105
+ }
106
+ isIgnored(node) {
107
+ if (this.isInstance(node, Text)) {
108
+ return false;
109
+ }
110
+ if (!this.isInstance(node, Element)) {
111
+ return true;
112
+ }
113
+ const tag = node.tagName.toUpperCase();
114
+ if (tag === 'LINK') {
115
+ const rel = node.getAttribute('rel');
116
+ const as = node.getAttribute('as');
117
+ return !((rel === null || rel === void 0 ? void 0 : rel.includes('stylesheet')) || as === "style" || as === "font");
118
+ }
119
+ return (tag === 'SCRIPT' ||
120
+ tag === 'NOSCRIPT' ||
121
+ tag === 'META' ||
122
+ tag === 'TITLE' ||
123
+ tag === 'BASE');
124
+ }
88
125
  sendNodeAttribute(id, node, name, value) {
89
126
  if (isSVGElement(node)) {
90
127
  if (name.substr(0, 6) === 'xlink:') {
@@ -97,7 +134,7 @@ class Observer {
97
134
  if (value.length > 1e5) {
98
135
  value = '';
99
136
  }
100
- this.app.send(new messages_1.SetNodeAttributeURLBased(id, name, value, utils_1.getBaseURI()));
137
+ this.app.send(new messages_1.SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
101
138
  }
102
139
  else {
103
140
  this.app.send(new messages_1.SetNodeAttribute(id, name, value));
@@ -113,7 +150,7 @@ class Observer {
113
150
  return;
114
151
  }
115
152
  if (name === 'value' &&
116
- node instanceof HTMLInputElement &&
153
+ this.isInstance(node, HTMLInputElement) &&
117
154
  node.type !== 'button' &&
118
155
  node.type !== 'reset' &&
119
156
  node.type !== 'submit') {
@@ -123,8 +160,8 @@ class Observer {
123
160
  this.app.send(new messages_1.RemoveNodeAttribute(id, name));
124
161
  return;
125
162
  }
126
- if (name === 'style' || name === 'href' && node instanceof HTMLLinkElement) {
127
- this.app.send(new messages_1.SetNodeAttributeURLBased(id, name, value, utils_1.getBaseURI()));
163
+ if (name === 'style' || name === 'href' && this.isInstance(node, HTMLLinkElement)) {
164
+ this.app.send(new messages_1.SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
128
165
  return;
129
166
  }
130
167
  if (name === 'href' || value.length > 1e5) {
@@ -133,8 +170,8 @@ class Observer {
133
170
  this.app.send(new messages_1.SetNodeAttribute(id, name, value));
134
171
  }
135
172
  sendNodeData(id, parentElement, data) {
136
- if (parentElement instanceof HTMLStyleElement || parentElement instanceof SVGStyleElement) {
137
- this.app.send(new messages_1.SetCSSDataURLBased(id, data, utils_1.getBaseURI()));
173
+ if (this.isInstance(parentElement, HTMLStyleElement) || this.isInstance(parentElement, SVGStyleElement)) {
174
+ this.app.send(new messages_1.SetCSSDataURLBased(id, data, this.app.getBaseHref()));
138
175
  return;
139
176
  }
140
177
  if (this.textMasked.has(id)) {
@@ -156,12 +193,12 @@ class Observer {
156
193
  this.recents[id] = r[1] || this.recents[id] || false;
157
194
  }
158
195
  bindTree(node) {
159
- if (isIgnored(node)) {
196
+ if (this.isIgnored(node)) {
160
197
  return;
161
198
  }
162
199
  this.bindNode(node);
163
200
  const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
164
- acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) !== undefined
201
+ acceptNode: (node) => this.isIgnored(node) || this.app.nodes.getID(node) !== undefined
165
202
  ? NodeFilter.FILTER_REJECT
166
203
  : NodeFilter.FILTER_ACCEPT,
167
204
  }, false);
@@ -178,7 +215,10 @@ class Observer {
178
215
  _commitNode(id, node) {
179
216
  const parent = node.parentNode;
180
217
  let parentID;
181
- if (id !== 0) {
218
+ if (this.isInstance(node, HTMLHtmlElement)) {
219
+ this.indexes[id] = 0;
220
+ }
221
+ else {
182
222
  if (parent === null) {
183
223
  this.unbindNode(node);
184
224
  return false;
@@ -193,7 +233,7 @@ class Observer {
193
233
  return false;
194
234
  }
195
235
  if (this.textMasked.has(parentID) ||
196
- (node instanceof Element && utils_1.hasOpenreplayAttribute(node, 'masked'))) {
236
+ (this.isInstance(node, Element) && utils_1.hasOpenreplayAttribute(node, 'masked'))) {
197
237
  this.textMasked.add(id);
198
238
  }
199
239
  let sibling = node.previousSibling;
@@ -216,7 +256,7 @@ class Observer {
216
256
  throw 'commitNode: missing node index';
217
257
  }
218
258
  if (isNew === true) {
219
- if (node instanceof Element) {
259
+ if (this.isInstance(node, Element)) {
220
260
  if (parentID !== undefined) {
221
261
  this.app.send(new messages_1.CreateElementNode(id, parentID, index, node.tagName, isSVGElement(node)));
222
262
  }
@@ -224,8 +264,12 @@ class Observer {
224
264
  const attr = node.attributes[i];
225
265
  this.sendNodeAttribute(id, node, attr.nodeName, attr.value);
226
266
  }
267
+ if (this.isInstance(node, HTMLIFrameElement) &&
268
+ (this.options.captureIFrames || node.getAttribute("data-openreplay-capture"))) {
269
+ this.handleIframe(node);
270
+ }
227
271
  }
228
- else if (node instanceof Text) {
272
+ else if (this.isInstance(node, Text)) {
229
273
  // for text node id != 0, hence parentID !== undefined and parent is Element
230
274
  this.app.send(new messages_1.CreateTextNode(id, parentID, index));
231
275
  this.sendNodeData(id, parent, node.data);
@@ -237,7 +281,7 @@ class Observer {
237
281
  }
238
282
  const attr = this.attributesList[id];
239
283
  if (attr !== undefined) {
240
- if (!(node instanceof Element)) {
284
+ if (!this.isInstance(node, Element)) {
241
285
  throw 'commitNode: node is not an element';
242
286
  }
243
287
  for (const name of attr) {
@@ -245,7 +289,7 @@ class Observer {
245
289
  }
246
290
  }
247
291
  if (this.textSet.has(id)) {
248
- if (!(node instanceof Text)) {
292
+ if (!this.isInstance(node, Text)) {
249
293
  throw 'commitNode: node is not a text';
250
294
  }
251
295
  // for text node id != 0, hence parent is Element
@@ -274,8 +318,42 @@ class Observer {
274
318
  }
275
319
  this.clear();
276
320
  }
321
+ handleIframe(iframe) {
322
+ const handle = () => {
323
+ const context = iframe.contentWindow;
324
+ const id = this.app.nodes.getID(iframe);
325
+ if (!context || id === undefined) {
326
+ return;
327
+ }
328
+ const observer = new Observer(this.app, this.options, context);
329
+ this.iframeObservers.push(observer);
330
+ observer.observeIframe(id, context);
331
+ };
332
+ this.app.attachEventListener(iframe, "load", handle);
333
+ handle();
334
+ }
335
+ // TODO: abstract common functionality, separate FrameObserver
336
+ observeIframe(id, context) {
337
+ const doc = context.document;
338
+ this.observer.observe(doc, {
339
+ childList: true,
340
+ attributes: true,
341
+ characterData: true,
342
+ subtree: true,
343
+ attributeOldValue: false,
344
+ characterDataOldValue: false,
345
+ });
346
+ this.bindTree(doc.documentElement);
347
+ const docID = this.app.nodes.getID(doc.documentElement);
348
+ if (docID === undefined) {
349
+ console.log("Wrong");
350
+ return;
351
+ }
352
+ this.app.send(messages_1.CreateIFrameDocument(id, docID));
353
+ this.commitNodes();
354
+ }
277
355
  observe() {
278
- this.observer.observe(document, {
356
+ this.observer.observe(this.context.document, {
279
357
  childList: true,
280
358
  attributes: true,
281
359
  characterData: true,
@@ -284,10 +362,12 @@ class Observer {
284
362
  characterDataOldValue: false,
285
363
  });
286
364
  this.app.send(new messages_1.CreateDocument());
287
- this.bindTree(document.documentElement);
365
+ this.bindTree(this.context.document.documentElement);
288
366
  this.commitNodes();
289
367
  }
290
368
  disconnect() {
369
+ this.iframeObservers.forEach(o => o.disconnect());
370
+ this.iframeObservers = [];
291
371
  this.observer.disconnect();
292
372
  this.clear();
293
373
  }
package/cjs/index.js CHANGED
@@ -23,13 +23,13 @@ const utils_1 = require("./utils");
23
23
  const DOCS_SETUP = '/installation/setup-or';
24
24
  function processOptions(obj) {
25
25
  if (obj == null) {
26
- console.error(`OpenReplay: invalid options argument type. Please, check documentation on https://docs.openreplay.com${DOCS_SETUP}`);
26
+ console.error(`OpenReplay: invalid options argument type. Please, check documentation on ${utils_1.DOCS_HOST}${DOCS_SETUP}`);
27
27
  return false;
28
28
  }
29
29
  if (typeof obj.projectKey !== 'string') {
30
30
  if (typeof obj.projectKey !== 'number') {
31
31
  if (typeof obj.projectID !== 'number') { // Back compatability
32
- console.error(`OpenReplay: projectKey is missing or wrong type (string is expected). Please, check https://docs.openreplay.com${DOCS_SETUP} for more information.`);
32
+ console.error(`OpenReplay: projectKey is missing or wrong type (string is expected). Please, check ${utils_1.DOCS_HOST}${DOCS_SETUP} for more information.`);
33
33
  return false;
34
34
  }
35
35
  else {
@@ -43,7 +43,7 @@ function processOptions(obj) {
43
43
  }
44
44
  }
45
45
  if (typeof obj.sessionToken !== 'string' && obj.sessionToken != null) {
46
- console.warn(`OpenReplay: invalid options argument type. Please, check documentation on https://docs.openreplay.com${DOCS_SETUP}`);
46
+ console.warn(`OpenReplay: invalid options argument type. Please, check documentation on ${utils_1.DOCS_HOST}${DOCS_SETUP}`);
47
47
  }
48
48
  return true;
49
49
  }
@@ -69,6 +69,10 @@ class API {
69
69
  if (!utils_1.IN_BROWSER || !processOptions(options)) {
70
70
  return;
71
71
  }
72
+ if (window.__OPENREPLAY__) {
73
+ console.error("OpenReplay: one tracker instance has been initialised already");
74
+ return;
75
+ }
72
76
  if (!options.__DISABLE_SECURE_MODE && location.protocol !== 'https:') {
73
77
  console.error("OpenReplay: Your website must be publicly accessible and running on SSL in order for OpenReplay to properly capture and replay the user session. You can disable this check by setting `__DISABLE_SECURE_MODE` option to `true` if you are testing in localhost. Keep in mind, that asset files on a local machine are not available to the outside world. This might affect tracking if you use css files.");
74
78
  return;
@@ -98,17 +102,17 @@ class API {
98
102
  performance_1.default(this.app, options);
99
103
  scroll_1.default(this.app);
100
104
  longtasks_1.default(this.app);
101
- window.__OPENREPLAY__ = window.__OPENREPLAY__ || this;
105
+ window.__OPENREPLAY__ = this;
102
106
  }
103
107
  else {
104
- console.log("OpenReplay: browser doesn't support API required for tracking.");
108
+ console.log("OpenReplay: browser doesn't support API required for tracking or doNotTrack is set to 1.");
105
109
  const req = new XMLHttpRequest();
106
110
  const orig = options.ingestPoint || app_1.DEFAULT_INGEST_POINT;
107
111
  req.open("POST", orig + "/v1/web/not-started");
108
112
  // no-cors issue only with text/plain or not-set Content-Type
109
113
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
110
114
  req.send(JSON.stringify({
111
- trackerVersion: '3.3.0',
115
+ trackerVersion: '3.4.1',
112
116
  projectKey: options.projectKey,
113
117
  doNotTrack,
114
118
  // TODO: add precise reason (an exact API missing)
@@ -130,7 +134,7 @@ class API {
130
134
  }
131
135
  start() {
132
136
  if (!utils_1.IN_BROWSER) {
133
- console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on https://docs.openreplay.com${DOCS_SETUP}`);
137
+ console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on ${utils_1.DOCS_HOST}${DOCS_SETUP}`);
134
138
  return;
135
139
  }
136
140
  if (this.app === null) {
@@ -434,4 +434,12 @@ declare class _MouseClick implements Message {
434
434
  encode(writer: Writer): boolean;
435
435
  }
436
436
  export declare const MouseClick: typeof _MouseClick & ((id: number, hesitationTime: number, label: string, selector: string) => _MouseClick);
437
+ declare class _CreateIFrameDocument implements Message {
438
+ frameID: number;
439
+ id: number;
440
+ readonly _id: number;
441
+ constructor(frameID: number, id: number);
442
+ encode(writer: Writer): boolean;
443
+ }
444
+ export declare const CreateIFrameDocument: typeof _CreateIFrameDocument & ((frameID: number, id: number) => _CreateIFrameDocument);
437
445
  export {};