@webex/internal-plugin-metrics 3.12.0-next.5 → 3.12.0-next.50
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 +274 -0
- package/dist/automated-user.js +19 -0
- package/dist/automated-user.js.map +1 -0
- package/dist/batcher.js +3 -0
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +635 -62
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +188 -78
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +5 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +16 -3
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +118 -5
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js +4 -0
- package/dist/metrics.types.js.map +1 -1
- package/dist/network-telemetry.js +610 -0
- package/dist/network-telemetry.js.map +1 -0
- package/dist/new-metrics.js +63 -17
- package/dist/new-metrics.js.map +1 -1
- package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
- package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/index.js +143 -0
- package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/types.js +7 -0
- package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
- package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
- package/dist/types/automated-user.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +208 -5
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +73 -14
- package/dist/types/call-diagnostic/config.d.ts +4 -0
- package/dist/types/config.d.ts +9 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/metrics.types.d.ts +7 -2
- package/dist/types/network-telemetry.d.ts +108 -0
- package/dist/types/new-metrics.d.ts +17 -1
- package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
- package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
- package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
- package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
- package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
- package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
- package/dist/unhandled-exception-telemetry/index.js +330 -0
- package/dist/unhandled-exception-telemetry/index.js.map +1 -0
- package/dist/unhandled-exception-telemetry/utils.js +105 -0
- package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
- package/package.json +12 -11
- package/src/automated-user.ts +16 -0
- package/src/batcher.js +4 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +781 -71
- package/src/call-diagnostic/call-diagnostic-metrics.ts +119 -16
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +5 -0
- package/src/call-diagnostic/config.ts +14 -0
- package/src/config.js +8 -0
- package/src/index.ts +16 -0
- package/src/metrics.js +123 -5
- package/src/metrics.types.ts +25 -3
- package/src/network-telemetry.ts +757 -0
- package/src/new-metrics.ts +56 -6
- package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
- package/src/privacy-and-security-permission-enricher/index.ts +142 -0
- package/src/privacy-and-security-permission-enricher/types.ts +21 -0
- package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
- package/src/unhandled-exception-telemetry/index.ts +403 -0
- package/src/unhandled-exception-telemetry/utils.ts +101 -0
- package/test/unit/spec/automated-user.ts +43 -0
- package/test/unit/spec/batcher.js +43 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +14 -2
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1424 -293
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +906 -159
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
- package/test/unit/spec/metrics.js +14 -5
- package/test/unit/spec/network-telemetry.ts +610 -0
- package/test/unit/spec/new-metrics.ts +203 -50
- package/test/unit/spec/prelogin-metrics-batcher.ts +71 -36
- package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
- package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
- package/test/unit/spec/unhandled-exception-telemetry.ts +688 -0
package/src/new-metrics.ts
CHANGED
|
@@ -19,17 +19,20 @@ import {
|
|
|
19
19
|
ClientEvent,
|
|
20
20
|
FeatureEvent,
|
|
21
21
|
EventPayload,
|
|
22
|
-
OperationalEvent,
|
|
23
22
|
MediaQualityEvent,
|
|
24
23
|
InternalEvent,
|
|
25
24
|
SubmitClientEventOptions,
|
|
26
25
|
Table,
|
|
27
26
|
DelayedClientEvent,
|
|
28
27
|
DelayedClientFeatureEvent,
|
|
28
|
+
PrivacyAndSecurityPermission,
|
|
29
29
|
} from './metrics.types';
|
|
30
30
|
import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
|
|
31
31
|
import {setMetricTimings} from './call-diagnostic/call-diagnostic-metrics.util';
|
|
32
32
|
import {generateCommonErrorMetadata} from './utils';
|
|
33
|
+
import {isAutomatedUser as detectAutomatedUser} from './automated-user';
|
|
34
|
+
import PrivacyAndSecurityPermissionEnricher from './privacy-and-security-permission-enricher';
|
|
35
|
+
import {startUnhandledExceptionTelemetry} from './unhandled-exception-telemetry';
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* Metrics plugin to centralize all types of metrics.
|
|
@@ -67,6 +70,8 @@ class Metrics extends WebexPlugin {
|
|
|
67
70
|
|
|
68
71
|
delayedClientFeatureEventsOverrides: Partial<DelayedClientFeatureEvent['options']> = {};
|
|
69
72
|
|
|
73
|
+
private privacyAndSecurityPermissionEnricher: PrivacyAndSecurityPermissionEnricher;
|
|
74
|
+
|
|
70
75
|
/**
|
|
71
76
|
* Constructor
|
|
72
77
|
* @param args
|
|
@@ -77,8 +82,19 @@ class Metrics extends WebexPlugin {
|
|
|
77
82
|
constructor(...args) {
|
|
78
83
|
super(...args);
|
|
79
84
|
|
|
85
|
+
this.privacyAndSecurityPermissionEnricher = new PrivacyAndSecurityPermissionEnricher(
|
|
86
|
+
(error) => {
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
this.webex.logger.error(
|
|
89
|
+
'NewMetrics: @submitClientEvent. Privacy and security permission enrichment failed.',
|
|
90
|
+
error
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
);
|
|
80
94
|
// @ts-ignore
|
|
81
95
|
this.callDiagnosticLatencies = new CallDiagnosticLatencies({}, {parent: this.webex});
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex});
|
|
82
98
|
this.onReady();
|
|
83
99
|
}
|
|
84
100
|
|
|
@@ -88,8 +104,6 @@ class Metrics extends WebexPlugin {
|
|
|
88
104
|
private onReady() {
|
|
89
105
|
// @ts-ignore
|
|
90
106
|
this.webex.once('ready', () => {
|
|
91
|
-
// @ts-ignore
|
|
92
|
-
this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex});
|
|
93
107
|
this.preLoginMetrics = new PreLoginMetrics(
|
|
94
108
|
// @ts-ignore
|
|
95
109
|
new PreLoginMetricsBatcher({}, {parent: this.webex}),
|
|
@@ -102,6 +116,8 @@ class Metrics extends WebexPlugin {
|
|
|
102
116
|
shouldDelay: this.delaySubmitClientEvents,
|
|
103
117
|
overrides: this.delayedClientEventsOverrides,
|
|
104
118
|
});
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
startUnhandledExceptionTelemetry(this.webex);
|
|
105
121
|
});
|
|
106
122
|
}
|
|
107
123
|
|
|
@@ -182,6 +198,13 @@ class Metrics extends WebexPlugin {
|
|
|
182
198
|
return this.businessMetrics?.isReadyToSubmitEvents() ?? false;
|
|
183
199
|
}
|
|
184
200
|
|
|
201
|
+
/**
|
|
202
|
+
* @returns whether the current user agent belongs to an automated user
|
|
203
|
+
*/
|
|
204
|
+
isAutomatedUser() {
|
|
205
|
+
return detectAutomatedUser();
|
|
206
|
+
}
|
|
207
|
+
|
|
185
208
|
/**
|
|
186
209
|
* Behavioral event
|
|
187
210
|
* @param args
|
|
@@ -325,7 +348,7 @@ class Metrics extends WebexPlugin {
|
|
|
325
348
|
payload?: RecursivePartial<FeatureEvent['payload']>;
|
|
326
349
|
options: any;
|
|
327
350
|
}) {
|
|
328
|
-
if (!this.
|
|
351
|
+
if (!this.isReady) {
|
|
329
352
|
// @ts-ignore
|
|
330
353
|
this.webex.logger.log(
|
|
331
354
|
`NewMetrics: @submitFeatureEvent. Attempted to submit before webex.ready. Event name: ${name}`
|
|
@@ -360,7 +383,7 @@ class Metrics extends WebexPlugin {
|
|
|
360
383
|
payload?: RecursivePartial<ClientEvent['payload']>;
|
|
361
384
|
options?: SubmitClientEventOptions;
|
|
362
385
|
}): Promise<any> {
|
|
363
|
-
if (!this.
|
|
386
|
+
if (!this.isReady) {
|
|
364
387
|
// @ts-ignore
|
|
365
388
|
this.webex.logger.log(
|
|
366
389
|
`NewMetrics: @submitClientEvent. Attempted to submit before webex.ready. Event name: ${name}`
|
|
@@ -373,14 +396,41 @@ class Metrics extends WebexPlugin {
|
|
|
373
396
|
options: {meetingId: options?.meetingId},
|
|
374
397
|
});
|
|
375
398
|
|
|
376
|
-
|
|
399
|
+
const enrichedPayload = this.privacyAndSecurityPermissionEnricher.enrich({
|
|
377
400
|
name,
|
|
378
401
|
payload,
|
|
402
|
+
scope: this.getPermissionScope(options),
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
return this.callDiagnosticMetrics.submitClientEvent({
|
|
406
|
+
name,
|
|
407
|
+
payload: enrichedPayload,
|
|
379
408
|
options,
|
|
380
409
|
delaySubmitEvent: this.delaySubmitClientEvents,
|
|
381
410
|
});
|
|
382
411
|
}
|
|
383
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Stores the latest browser permission state supplied by the client.
|
|
415
|
+
* @param permission latest normalized permission snapshot
|
|
416
|
+
*/
|
|
417
|
+
public setPrivacyAndSecurityPermission(permission: PrivacyAndSecurityPermission): void {
|
|
418
|
+
this.privacyAndSecurityPermissionEnricher.setPermission(permission);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Resolves event options to the call identity used by Call Diagnostic where possible.
|
|
423
|
+
* @param options client event options
|
|
424
|
+
* @returns the permission history scope
|
|
425
|
+
*/
|
|
426
|
+
private getPermissionScope(options?: SubmitClientEventOptions): string {
|
|
427
|
+
const meeting = options?.meetingId
|
|
428
|
+
? (this as any).webex.meetings?.getBasicMeetingInformation?.(options.meetingId)
|
|
429
|
+
: undefined;
|
|
430
|
+
|
|
431
|
+
return options?.correlationId ?? meeting?.correlationId ?? 'default';
|
|
432
|
+
}
|
|
433
|
+
|
|
384
434
|
/**
|
|
385
435
|
* Issue request to alias a user's pre-login ID with their CI UUID
|
|
386
436
|
* @param {string} preLoginId
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type {ClientEvent} from '../metrics.types';
|
|
2
|
+
import type {PermissionEnrichmentPolicy} from './types';
|
|
3
|
+
|
|
4
|
+
export const CAMERA_AND_MICROPHONE_PERMISSION_EVENTS = new Set<ClientEvent['name']>([
|
|
5
|
+
'client.call.initiated',
|
|
6
|
+
'client.media.capabilities',
|
|
7
|
+
'client.ice.end',
|
|
8
|
+
'client.locus.join.request',
|
|
9
|
+
'client.locus.join.response',
|
|
10
|
+
'client.media-engine.ready',
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
export const MEDIA_TX_PERMISSION_EVENTS = new Set<ClientEvent['name']>([
|
|
14
|
+
'client.media.tx.start',
|
|
15
|
+
'client.media.tx.stop',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
export const CONTENT_SHARE_PERMISSION_EVENTS = new Set<ClientEvent['name']>([
|
|
19
|
+
'client.share.initiated',
|
|
20
|
+
'client.share.floor-grant.request',
|
|
21
|
+
'client.share.floor-granted.local',
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export const FINAL_PERMISSION_EVENTS = new Set<ClientEvent['name']>([
|
|
25
|
+
'client.call.leave',
|
|
26
|
+
'client.call.remote-ended',
|
|
27
|
+
'client.call.aborted',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
export const NO_PERMISSION_ENRICHMENT: PermissionEnrichmentPolicy = {
|
|
31
|
+
resources: [],
|
|
32
|
+
terminal: false,
|
|
33
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type {ClientEventPayload, PrivacyAndSecurityPermission} from '../metrics.types';
|
|
2
|
+
import {
|
|
3
|
+
CAMERA_AND_MICROPHONE_PERMISSION_EVENTS,
|
|
4
|
+
CONTENT_SHARE_PERMISSION_EVENTS,
|
|
5
|
+
FINAL_PERMISSION_EVENTS,
|
|
6
|
+
MEDIA_TX_PERMISSION_EVENTS,
|
|
7
|
+
NO_PERMISSION_ENRICHMENT,
|
|
8
|
+
} from './constants';
|
|
9
|
+
import type {
|
|
10
|
+
PermissionEnrichmentContext,
|
|
11
|
+
PermissionEnrichmentPolicy,
|
|
12
|
+
PermissionEnrichmentRule,
|
|
13
|
+
} from './types';
|
|
14
|
+
import {
|
|
15
|
+
getChangedPermission,
|
|
16
|
+
projectPrivacyAndSecurityPermission,
|
|
17
|
+
resolveContentShareResources,
|
|
18
|
+
resolveMediaResources,
|
|
19
|
+
} from './utils';
|
|
20
|
+
|
|
21
|
+
export const PERMISSION_ENRICHMENT_RULES = [
|
|
22
|
+
{
|
|
23
|
+
events: CAMERA_AND_MICROPHONE_PERMISSION_EVENTS,
|
|
24
|
+
resolve: () => ({resources: ['camera', 'microphone'], terminal: false}),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
events: MEDIA_TX_PERMISSION_EVENTS,
|
|
28
|
+
resolve: (payload) => ({resources: resolveMediaResources(payload), terminal: false}),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
events: CONTENT_SHARE_PERMISSION_EVENTS,
|
|
32
|
+
resolve: (payload) => ({
|
|
33
|
+
resources: resolveContentShareResources(payload),
|
|
34
|
+
terminal: false,
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
events: FINAL_PERMISSION_EVENTS,
|
|
39
|
+
resolve: () => ({resources: ['camera', 'microphone', 'contentShare'], terminal: true}),
|
|
40
|
+
},
|
|
41
|
+
] satisfies readonly PermissionEnrichmentRule[];
|
|
42
|
+
|
|
43
|
+
const resolvePermissionEnrichmentPolicy = (
|
|
44
|
+
name: PermissionEnrichmentContext['name'],
|
|
45
|
+
payload?: ClientEventPayload
|
|
46
|
+
): PermissionEnrichmentPolicy =>
|
|
47
|
+
PERMISSION_ENRICHMENT_RULES.find(({events}) => events.has(name))?.resolve(payload) ??
|
|
48
|
+
NO_PERMISSION_ENRICHMENT;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Enriches eligible client events with relevant browser permission changes.
|
|
52
|
+
*/
|
|
53
|
+
export default class PrivacyAndSecurityPermissionEnricher {
|
|
54
|
+
private permission?: PrivacyAndSecurityPermission;
|
|
55
|
+
|
|
56
|
+
private lastReported = new Map<string, PrivacyAndSecurityPermission>();
|
|
57
|
+
|
|
58
|
+
private readonly onEnrichmentError: (error: unknown) => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates a permission enricher.
|
|
62
|
+
* @param {Function} onEnrichmentError permission enrichment error handler
|
|
63
|
+
*/
|
|
64
|
+
constructor(onEnrichmentError: (error: unknown) => void) {
|
|
65
|
+
this.onEnrichmentError = onEnrichmentError;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Stores the latest normalized browser permission state.
|
|
70
|
+
* @param {PrivacyAndSecurityPermission} permission permission snapshot
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
public setPermission(permission: PrivacyAndSecurityPermission): void {
|
|
74
|
+
this.permission = projectPrivacyAndSecurityPermission(permission, [
|
|
75
|
+
'camera',
|
|
76
|
+
'microphone',
|
|
77
|
+
'contentShare',
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns the original payload or a copy enriched with relevant permission changes.
|
|
83
|
+
* @param {PermissionEnrichmentContext} context event context and permission history scope
|
|
84
|
+
* @returns {ClientEventPayload | undefined}
|
|
85
|
+
*/
|
|
86
|
+
public enrich({
|
|
87
|
+
name,
|
|
88
|
+
payload,
|
|
89
|
+
scope,
|
|
90
|
+
}: PermissionEnrichmentContext): ClientEventPayload | undefined {
|
|
91
|
+
const policy = resolvePermissionEnrichmentPolicy(name, payload);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
if (payload?.privacyAndSecurityPermission !== undefined) {
|
|
95
|
+
// An explicitly supplied permission payload is authoritative for this event.
|
|
96
|
+
if (!policy.terminal) {
|
|
97
|
+
this.lastReported.set(scope, {
|
|
98
|
+
...this.lastReported.get(scope),
|
|
99
|
+
...(payload.privacyAndSecurityPermission as PrivacyAndSecurityPermission),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return payload;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (policy.resources.length === 0) {
|
|
107
|
+
return payload;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const projectedPermission = this.permission
|
|
111
|
+
? projectPrivacyAndSecurityPermission(this.permission, policy.resources)
|
|
112
|
+
: undefined;
|
|
113
|
+
|
|
114
|
+
if (!projectedPermission) {
|
|
115
|
+
return payload;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (policy.terminal) {
|
|
119
|
+
return {...payload, privacyAndSecurityPermission: projectedPermission};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const lastReported = this.lastReported.get(scope) ?? {};
|
|
123
|
+
const changedPermission = getChangedPermission(projectedPermission, lastReported);
|
|
124
|
+
|
|
125
|
+
if (!changedPermission) {
|
|
126
|
+
return payload;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.lastReported.set(scope, {...lastReported, ...changedPermission});
|
|
130
|
+
|
|
131
|
+
return {...payload, privacyAndSecurityPermission: changedPermission};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.onEnrichmentError(error);
|
|
134
|
+
|
|
135
|
+
return payload;
|
|
136
|
+
} finally {
|
|
137
|
+
if (policy.terminal) {
|
|
138
|
+
this.lastReported.delete(scope);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClientEvent,
|
|
3
|
+
ClientEventPayload,
|
|
4
|
+
PrivacyAndSecurityPermissionResource,
|
|
5
|
+
} from '../metrics.types';
|
|
6
|
+
|
|
7
|
+
export type PermissionEnrichmentPolicy = {
|
|
8
|
+
resources: readonly PrivacyAndSecurityPermissionResource[];
|
|
9
|
+
terminal: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type PermissionEnrichmentRule = {
|
|
13
|
+
events: ReadonlySet<ClientEvent['name']>;
|
|
14
|
+
resolve: (payload?: ClientEventPayload) => PermissionEnrichmentPolicy;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type PermissionEnrichmentContext = {
|
|
18
|
+
name: ClientEvent['name'];
|
|
19
|
+
payload?: ClientEventPayload;
|
|
20
|
+
scope: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {isEqual} from 'lodash';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ClientEventPayload,
|
|
5
|
+
PrivacyAndSecurityPermission,
|
|
6
|
+
PrivacyAndSecurityPermissionResource,
|
|
7
|
+
} from '../metrics.types';
|
|
8
|
+
|
|
9
|
+
export const resolveMediaResources = (
|
|
10
|
+
payload?: ClientEventPayload
|
|
11
|
+
): PrivacyAndSecurityPermissionResource[] => {
|
|
12
|
+
switch (payload?.mediaType) {
|
|
13
|
+
case 'audio':
|
|
14
|
+
return ['microphone'];
|
|
15
|
+
case 'video':
|
|
16
|
+
return ['camera'];
|
|
17
|
+
case 'share':
|
|
18
|
+
return ['contentShare'];
|
|
19
|
+
default:
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const resolveContentShareResources = (
|
|
25
|
+
payload?: ClientEventPayload
|
|
26
|
+
): PrivacyAndSecurityPermissionResource[] => {
|
|
27
|
+
if (payload?.mediaType !== 'share') {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return ['contentShare'];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const copyPermissionState = (
|
|
35
|
+
source: PrivacyAndSecurityPermission,
|
|
36
|
+
target: PrivacyAndSecurityPermission,
|
|
37
|
+
resource: PrivacyAndSecurityPermissionResource
|
|
38
|
+
): void => {
|
|
39
|
+
switch (resource) {
|
|
40
|
+
case 'camera':
|
|
41
|
+
if (source.camera) {
|
|
42
|
+
target.camera = {...source.camera};
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
case 'microphone':
|
|
46
|
+
if (source.microphone) {
|
|
47
|
+
target.microphone = {...source.microphone};
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case 'contentShare':
|
|
51
|
+
if (source.contentShare) {
|
|
52
|
+
target.contentShare = {...source.contentShare};
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const projectPrivacyAndSecurityPermission = (
|
|
61
|
+
permission: PrivacyAndSecurityPermission,
|
|
62
|
+
resources: readonly PrivacyAndSecurityPermissionResource[]
|
|
63
|
+
): PrivacyAndSecurityPermission | undefined => {
|
|
64
|
+
const projectedPermission: PrivacyAndSecurityPermission = {};
|
|
65
|
+
|
|
66
|
+
resources.forEach((resource) => {
|
|
67
|
+
copyPermissionState(permission, projectedPermission, resource);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return Object.keys(projectedPermission).length > 0 ? projectedPermission : undefined;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const getChangedPermission = (
|
|
74
|
+
current: PrivacyAndSecurityPermission,
|
|
75
|
+
previous: PrivacyAndSecurityPermission
|
|
76
|
+
): PrivacyAndSecurityPermission | undefined => {
|
|
77
|
+
const changedResources = (Object.keys(current) as PrivacyAndSecurityPermissionResource[]).filter(
|
|
78
|
+
(resource) => !isEqual(current[resource], previous[resource])
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return projectPrivacyAndSecurityPermission(current, changedResources);
|
|
82
|
+
};
|