@newrelic/browser-agent 1.321.0-rc.10 → 1.321.0-rc.12
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/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/features/generic_events/aggregate/index.js +3 -13
- package/dist/cjs/features/generic_events/instrument/index.js +41 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/features/generic_events/aggregate/index.js +3 -13
- package/dist/esm/features/generic_events/instrument/index.js +41 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/features/generic_events/aggregate/index.js +3 -13
- package/src/features/generic_events/instrument/index.js +39 -1
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.321.0-rc.
|
|
20
|
+
const VERSION = exports.VERSION = "1.321.0-rc.12";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.321.0-rc.
|
|
20
|
+
const VERSION = exports.VERSION = "1.321.0-rc.12";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -307,21 +307,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
307
307
|
}, this.featureName, this.ee);
|
|
308
308
|
}
|
|
309
309
|
if (!agentRef.init.feature_flags.includes('no_spv')) {
|
|
310
|
-
(0, _registerHandler.registerHandler)('spv',
|
|
310
|
+
(0, _registerHandler.registerHandler)('spv', (violation, timestamp) => {
|
|
311
311
|
this.addEvent({
|
|
312
312
|
eventType: _events.EVENT_TYPES.SPV,
|
|
313
|
-
timestamp: this.#toEpoch(
|
|
314
|
-
|
|
315
|
-
documentUri: evt.documentURI,
|
|
316
|
-
effectiveDirective: evt.effectiveDirective,
|
|
317
|
-
originalPolicy: evt.originalPolicy,
|
|
318
|
-
sourceFile: evt.sourceFile,
|
|
319
|
-
statusCode: evt.statusCode,
|
|
320
|
-
lineNumber: evt.lineNumber,
|
|
321
|
-
columnNumber: evt.columnNumber,
|
|
322
|
-
disposition: evt.disposition,
|
|
323
|
-
sample: evt.sample,
|
|
324
|
-
referrer: evt.referrer
|
|
313
|
+
timestamp: this.#toEpoch(timestamp),
|
|
314
|
+
...violation
|
|
325
315
|
});
|
|
326
316
|
}, this.featureName, this.ee);
|
|
327
317
|
}
|
|
@@ -7,6 +7,7 @@ exports.Instrument = exports.GenericEvents = void 0;
|
|
|
7
7
|
var _runtime = require("../../../common/constants/runtime");
|
|
8
8
|
var _handle = require("../../../common/event-emitter/handle");
|
|
9
9
|
var _eventListenerOpts = require("../../../common/event-listener/event-listener-opts");
|
|
10
|
+
var _now = require("../../../common/timing/now");
|
|
10
11
|
var _invoke = require("../../../common/util/invoke");
|
|
11
12
|
var _addPageAction = require("../../../loaders/api/addPageAction");
|
|
12
13
|
var _finished = require("../../../loaders/api/finished");
|
|
@@ -56,8 +57,26 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
if (securityPolicyViolationEnabled) {
|
|
60
|
+
/** ReportingObserver's `csp-violation` type isn't reliably enabled everywhere out of the box:
|
|
61
|
+
* - Safari only delivers it when the page sets a report-to CSP directive -- https://bugs.webkit.org/show_bug.cgi?id=320750;
|
|
62
|
+
* - Firefox ships it behind the `dom.reporting.enabled` pref, which defaults to false;
|
|
63
|
+
* So it's only used for violations that occur before the agent loaded, targeting Chromium browsers. `buffered: true` replays
|
|
64
|
+
* that backlog in the observer's first callback invocation, after which it's disconnected and all future violations are
|
|
65
|
+
* covered by securitypolicyviolation, which is reliable across all browsers. */
|
|
66
|
+
if (typeof _runtime.globalScope.ReportingObserver === 'function') {
|
|
67
|
+
const cspObserver = new _runtime.globalScope.ReportingObserver(reports => {
|
|
68
|
+
reports.forEach(report => {
|
|
69
|
+
(0, _handle.handle)('spv', [normalizeCspViolation(report), (0, _now.now)()], undefined, _features.FEATURE_NAMES.genericEvents, this.ee);
|
|
70
|
+
});
|
|
71
|
+
cspObserver.disconnect();
|
|
72
|
+
}, {
|
|
73
|
+
types: ['csp-violation'],
|
|
74
|
+
buffered: true
|
|
75
|
+
});
|
|
76
|
+
cspObserver.observe();
|
|
77
|
+
}
|
|
59
78
|
_runtime.globalScope.addEventListener('securitypolicyviolation', evt => {
|
|
60
|
-
(0, _handle.handle)('spv', [evt], undefined, _features.FEATURE_NAMES.genericEvents, this.ee);
|
|
79
|
+
(0, _handle.handle)('spv', [normalizeCspViolation(evt), evt.timeStamp], undefined, _features.FEATURE_NAMES.genericEvents, this.ee);
|
|
61
80
|
}, (0, _eventListenerOpts.eventListenerOpts)(false, this.removeOnAbort.signal));
|
|
62
81
|
}
|
|
63
82
|
if (_runtime.isBrowserScope) {
|
|
@@ -122,5 +141,26 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
122
141
|
if (genericEventSourceConfigs.some(x => x)) this.importAggregator(agentRef, () => Promise.resolve().then(() => _interopRequireWildcard(require(/* webpackChunkName: "generic_events-aggregate" */'../aggregate'))));else this.deregisterDrain();
|
|
123
142
|
}
|
|
124
143
|
}
|
|
144
|
+
/** `Report.body` (ReportingObserver) and `SecurityPolicyViolationEvent` (securitypolicyviolation) describe the same
|
|
145
|
+
* violation with differently-named/shaped fields -- collapse both into one shape so downstream code doesn't care
|
|
146
|
+
* which mechanism produced it. `source` is either of those: a Report (fields under `.body`, URLs as blockedURL/
|
|
147
|
+
* documentURL) or the event (fields at the top level, URLs as blockedURI/documentURI). Also normalizes disposition's
|
|
148
|
+
* "reporting" (Report body) to "report" (event) so the value is consistent regardless of source. */
|
|
125
149
|
exports.Instrument = Instrument;
|
|
150
|
+
function normalizeCspViolation(source) {
|
|
151
|
+
const body = source.body ?? source;
|
|
152
|
+
return {
|
|
153
|
+
blockedUrl: body.blockedURL ?? source.blockedURI,
|
|
154
|
+
documentUrl: body.documentURL ?? source.documentURI,
|
|
155
|
+
effectiveDirective: body.effectiveDirective,
|
|
156
|
+
originalPolicy: body.originalPolicy,
|
|
157
|
+
sourceFile: body.sourceFile,
|
|
158
|
+
statusCode: body.statusCode,
|
|
159
|
+
lineNumber: body.lineNumber,
|
|
160
|
+
columnNumber: body.columnNumber,
|
|
161
|
+
disposition: body.disposition === 'reporting' ? 'report' : body.disposition,
|
|
162
|
+
sample: body.sample,
|
|
163
|
+
referrer: body.referrer
|
|
164
|
+
};
|
|
165
|
+
}
|
|
126
166
|
const GenericEvents = exports.GenericEvents = Instrument;
|
|
@@ -300,21 +300,11 @@ export class Aggregate extends AggregateBase {
|
|
|
300
300
|
}, this.featureName, this.ee);
|
|
301
301
|
}
|
|
302
302
|
if (!agentRef.init.feature_flags.includes('no_spv')) {
|
|
303
|
-
registerHandler('spv',
|
|
303
|
+
registerHandler('spv', (violation, timestamp) => {
|
|
304
304
|
this.addEvent({
|
|
305
305
|
eventType: EVENT_TYPES.SPV,
|
|
306
|
-
timestamp: this.#toEpoch(
|
|
307
|
-
|
|
308
|
-
documentUri: evt.documentURI,
|
|
309
|
-
effectiveDirective: evt.effectiveDirective,
|
|
310
|
-
originalPolicy: evt.originalPolicy,
|
|
311
|
-
sourceFile: evt.sourceFile,
|
|
312
|
-
statusCode: evt.statusCode,
|
|
313
|
-
lineNumber: evt.lineNumber,
|
|
314
|
-
columnNumber: evt.columnNumber,
|
|
315
|
-
disposition: evt.disposition,
|
|
316
|
-
sample: evt.sample,
|
|
317
|
-
referrer: evt.referrer
|
|
306
|
+
timestamp: this.#toEpoch(timestamp),
|
|
307
|
+
...violation
|
|
318
308
|
});
|
|
319
309
|
}, this.featureName, this.ee);
|
|
320
310
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { globalScope, isBrowserScope } from '../../../common/constants/runtime';
|
|
7
7
|
import { handle } from '../../../common/event-emitter/handle';
|
|
8
8
|
import { eventListenerOpts, windowAddEventListener } from '../../../common/event-listener/event-listener-opts';
|
|
9
|
+
import { now } from '../../../common/timing/now';
|
|
9
10
|
import { debounce } from '../../../common/util/invoke';
|
|
10
11
|
import { setupAddPageActionAPI } from '../../../loaders/api/addPageAction';
|
|
11
12
|
import { setupFinishedAPI } from '../../../loaders/api/finished';
|
|
@@ -51,8 +52,26 @@ export class Instrument extends InstrumentBase {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
if (securityPolicyViolationEnabled) {
|
|
55
|
+
/** ReportingObserver's `csp-violation` type isn't reliably enabled everywhere out of the box:
|
|
56
|
+
* - Safari only delivers it when the page sets a report-to CSP directive -- https://bugs.webkit.org/show_bug.cgi?id=320750;
|
|
57
|
+
* - Firefox ships it behind the `dom.reporting.enabled` pref, which defaults to false;
|
|
58
|
+
* So it's only used for violations that occur before the agent loaded, targeting Chromium browsers. `buffered: true` replays
|
|
59
|
+
* that backlog in the observer's first callback invocation, after which it's disconnected and all future violations are
|
|
60
|
+
* covered by securitypolicyviolation, which is reliable across all browsers. */
|
|
61
|
+
if (typeof globalScope.ReportingObserver === 'function') {
|
|
62
|
+
const cspObserver = new globalScope.ReportingObserver(reports => {
|
|
63
|
+
reports.forEach(report => {
|
|
64
|
+
handle('spv', [normalizeCspViolation(report), now()], undefined, FEATURE_NAMES.genericEvents, this.ee);
|
|
65
|
+
});
|
|
66
|
+
cspObserver.disconnect();
|
|
67
|
+
}, {
|
|
68
|
+
types: ['csp-violation'],
|
|
69
|
+
buffered: true
|
|
70
|
+
});
|
|
71
|
+
cspObserver.observe();
|
|
72
|
+
}
|
|
54
73
|
globalScope.addEventListener('securitypolicyviolation', evt => {
|
|
55
|
-
handle('spv', [evt], undefined, FEATURE_NAMES.genericEvents, this.ee);
|
|
74
|
+
handle('spv', [normalizeCspViolation(evt), evt.timeStamp], undefined, FEATURE_NAMES.genericEvents, this.ee);
|
|
56
75
|
}, eventListenerOpts(false, this.removeOnAbort.signal));
|
|
57
76
|
}
|
|
58
77
|
if (isBrowserScope) {
|
|
@@ -117,4 +136,25 @@ export class Instrument extends InstrumentBase {
|
|
|
117
136
|
if (genericEventSourceConfigs.some(x => x)) this.importAggregator(agentRef, () => import(/* webpackChunkName: "generic_events-aggregate" */'../aggregate'));else this.deregisterDrain();
|
|
118
137
|
}
|
|
119
138
|
}
|
|
139
|
+
/** `Report.body` (ReportingObserver) and `SecurityPolicyViolationEvent` (securitypolicyviolation) describe the same
|
|
140
|
+
* violation with differently-named/shaped fields -- collapse both into one shape so downstream code doesn't care
|
|
141
|
+
* which mechanism produced it. `source` is either of those: a Report (fields under `.body`, URLs as blockedURL/
|
|
142
|
+
* documentURL) or the event (fields at the top level, URLs as blockedURI/documentURI). Also normalizes disposition's
|
|
143
|
+
* "reporting" (Report body) to "report" (event) so the value is consistent regardless of source. */
|
|
144
|
+
function normalizeCspViolation(source) {
|
|
145
|
+
const body = source.body ?? source;
|
|
146
|
+
return {
|
|
147
|
+
blockedUrl: body.blockedURL ?? source.blockedURI,
|
|
148
|
+
documentUrl: body.documentURL ?? source.documentURI,
|
|
149
|
+
effectiveDirective: body.effectiveDirective,
|
|
150
|
+
originalPolicy: body.originalPolicy,
|
|
151
|
+
sourceFile: body.sourceFile,
|
|
152
|
+
statusCode: body.statusCode,
|
|
153
|
+
lineNumber: body.lineNumber,
|
|
154
|
+
columnNumber: body.columnNumber,
|
|
155
|
+
disposition: body.disposition === 'reporting' ? 'report' : body.disposition,
|
|
156
|
+
sample: body.sample,
|
|
157
|
+
referrer: body.referrer
|
|
158
|
+
};
|
|
159
|
+
}
|
|
120
160
|
export const GenericEvents = Instrument;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IAGjC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IAGjC,2BAwRC;IAtRC,gCAAkG;IAIlG,uBAA0C;IAqR5C;;;;;;;;;;;;OAYG;IACH,eAJW,MAAM,YAAC,WACP,MAAM,YAAC,QAkCjB;IAED,6CAEC;IAED;;;MAEC;;CAsBF;8BArX6B,4BAA4B;2BAI/B,gCAAgC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/instrument/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/instrument/index.js"],"names":[],"mappings":"AAyBA;IACE,2BAAiC;IACjC,2BA0HC;IAnGC,+BAA0C;IAC1C,yBAGC;CAgGJ;AAuBD,8CAAuC;+BA9JR,6BAA6B"}
|
package/package.json
CHANGED
|
@@ -291,21 +291,11 @@ export class Aggregate extends AggregateBase {
|
|
|
291
291
|
}, this.featureName, this.ee)
|
|
292
292
|
}
|
|
293
293
|
if (!agentRef.init.feature_flags.includes('no_spv')) {
|
|
294
|
-
registerHandler('spv', (
|
|
294
|
+
registerHandler('spv', (violation, timestamp) => {
|
|
295
295
|
this.addEvent({
|
|
296
296
|
eventType: EVENT_TYPES.SPV,
|
|
297
|
-
timestamp: this.#toEpoch(
|
|
298
|
-
|
|
299
|
-
documentUri: evt.documentURI,
|
|
300
|
-
effectiveDirective: evt.effectiveDirective,
|
|
301
|
-
originalPolicy: evt.originalPolicy,
|
|
302
|
-
sourceFile: evt.sourceFile,
|
|
303
|
-
statusCode: evt.statusCode,
|
|
304
|
-
lineNumber: evt.lineNumber,
|
|
305
|
-
columnNumber: evt.columnNumber,
|
|
306
|
-
disposition: evt.disposition,
|
|
307
|
-
sample: evt.sample,
|
|
308
|
-
referrer: evt.referrer
|
|
297
|
+
timestamp: this.#toEpoch(timestamp),
|
|
298
|
+
...violation
|
|
309
299
|
})
|
|
310
300
|
}, this.featureName, this.ee)
|
|
311
301
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { globalScope, isBrowserScope } from '../../../common/constants/runtime'
|
|
7
7
|
import { handle } from '../../../common/event-emitter/handle'
|
|
8
8
|
import { eventListenerOpts, windowAddEventListener } from '../../../common/event-listener/event-listener-opts'
|
|
9
|
+
import { now } from '../../../common/timing/now'
|
|
9
10
|
import { debounce } from '../../../common/util/invoke'
|
|
10
11
|
import { setupAddPageActionAPI } from '../../../loaders/api/addPageAction'
|
|
11
12
|
import { setupFinishedAPI } from '../../../loaders/api/finished'
|
|
@@ -61,8 +62,24 @@ export class Instrument extends InstrumentBase {
|
|
|
61
62
|
})
|
|
62
63
|
}
|
|
63
64
|
if (securityPolicyViolationEnabled) {
|
|
65
|
+
/** ReportingObserver's `csp-violation` type isn't reliably enabled everywhere out of the box:
|
|
66
|
+
* - Safari only delivers it when the page sets a report-to CSP directive -- https://bugs.webkit.org/show_bug.cgi?id=320750;
|
|
67
|
+
* - Firefox ships it behind the `dom.reporting.enabled` pref, which defaults to false;
|
|
68
|
+
* So it's only used for violations that occur before the agent loaded, targeting Chromium browsers. `buffered: true` replays
|
|
69
|
+
* that backlog in the observer's first callback invocation, after which it's disconnected and all future violations are
|
|
70
|
+
* covered by securitypolicyviolation, which is reliable across all browsers. */
|
|
71
|
+
if (typeof globalScope.ReportingObserver === 'function') {
|
|
72
|
+
const cspObserver = new globalScope.ReportingObserver((reports) => {
|
|
73
|
+
reports.forEach(report => {
|
|
74
|
+
handle('spv', [normalizeCspViolation(report), now()], undefined, FEATURE_NAMES.genericEvents, this.ee)
|
|
75
|
+
})
|
|
76
|
+
cspObserver.disconnect()
|
|
77
|
+
}, { types: ['csp-violation'], buffered: true })
|
|
78
|
+
cspObserver.observe()
|
|
79
|
+
}
|
|
80
|
+
|
|
64
81
|
globalScope.addEventListener('securitypolicyviolation', (evt) => {
|
|
65
|
-
handle('spv', [evt], undefined, FEATURE_NAMES.genericEvents, this.ee)
|
|
82
|
+
handle('spv', [normalizeCspViolation(evt), evt.timeStamp], undefined, FEATURE_NAMES.genericEvents, this.ee)
|
|
66
83
|
}, eventListenerOpts(false, this.removeOnAbort.signal))
|
|
67
84
|
}
|
|
68
85
|
if (isBrowserScope) {
|
|
@@ -132,5 +149,26 @@ export class Instrument extends InstrumentBase {
|
|
|
132
149
|
else this.deregisterDrain()
|
|
133
150
|
}
|
|
134
151
|
}
|
|
152
|
+
/** `Report.body` (ReportingObserver) and `SecurityPolicyViolationEvent` (securitypolicyviolation) describe the same
|
|
153
|
+
* violation with differently-named/shaped fields -- collapse both into one shape so downstream code doesn't care
|
|
154
|
+
* which mechanism produced it. `source` is either of those: a Report (fields under `.body`, URLs as blockedURL/
|
|
155
|
+
* documentURL) or the event (fields at the top level, URLs as blockedURI/documentURI). Also normalizes disposition's
|
|
156
|
+
* "reporting" (Report body) to "report" (event) so the value is consistent regardless of source. */
|
|
157
|
+
function normalizeCspViolation (source) {
|
|
158
|
+
const body = source.body ?? source
|
|
159
|
+
return {
|
|
160
|
+
blockedUrl: body.blockedURL ?? source.blockedURI,
|
|
161
|
+
documentUrl: body.documentURL ?? source.documentURI,
|
|
162
|
+
effectiveDirective: body.effectiveDirective,
|
|
163
|
+
originalPolicy: body.originalPolicy,
|
|
164
|
+
sourceFile: body.sourceFile,
|
|
165
|
+
statusCode: body.statusCode,
|
|
166
|
+
lineNumber: body.lineNumber,
|
|
167
|
+
columnNumber: body.columnNumber,
|
|
168
|
+
disposition: body.disposition === 'reporting' ? 'report' : body.disposition,
|
|
169
|
+
sample: body.sample,
|
|
170
|
+
referrer: body.referrer
|
|
171
|
+
}
|
|
172
|
+
}
|
|
135
173
|
|
|
136
174
|
export const GenericEvents = Instrument
|