@corbado/observe 1.8.0 → 1.9.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.
- package/dist/analysis/client.mjs +82 -56
- package/dist/analysis/config-manager.mjs +172 -18
- package/dist/analysis/config.mjs +12 -4
- package/dist/analysis/device-info-manager.mjs +16 -1
- package/dist/analysis/device.mjs +88 -10
- package/dist/analysis/handoff.mjs +7 -0
- package/dist/analysis/low-events/grouped-input-tracker.mjs +148 -33
- package/dist/analysis/low-events/input-tracker.mjs +138 -59
- package/dist/analysis/low-events/shared-window-observer.mjs +148 -77
- package/dist/analysis/low-events/viewport-batcher.mjs +3 -3
- package/dist/analysis/queue.mjs +75 -8
- package/dist/analysis/{low-events/input-paste-observer.mjs → readers/input-paste.mjs} +2 -2
- package/dist/analysis/readers/input.mjs +61 -0
- package/dist/analysis/readers/loader-global.mjs +15 -0
- package/dist/analysis/readers/network.mjs +14 -0
- package/dist/analysis/readers/page.mjs +30 -0
- package/dist/analysis/readers/storage.mjs +28 -0
- package/dist/analysis/{utils → readers}/web-lock.mjs +6 -2
- package/dist/analysis/readers/window-events.mjs +48 -0
- package/dist/analysis/storage/index.mjs +61 -9
- package/dist/analysis/store/event-store.mjs +34 -16
- package/dist/analysis/transports/fetch.mjs +45 -3
- package/dist/analysis/utils/email-link-operation-full.mjs +22 -2
- package/dist/analysis/utils/email-otp-operation-full.mjs +0 -1
- package/dist/analysis/utils/form-operation-full.mjs +0 -1
- package/dist/analysis/utils/operation-full-provide-identifier-with-cui.mjs +6 -6
- package/dist/analysis/utils/passkey-enrollment-operation-full.mjs +9 -6
- package/dist/analysis/utils/passkey-login-operation-full.mjs +10 -5
- package/dist/analysis/utils/password-login-operation-full.mjs +8 -4
- package/dist/analysis/utils/password-manager-sampler.mjs +44 -4
- package/dist/analysis/utils/sms-otp-operation-full.mjs +0 -1
- package/dist/analysis/utils/totp-operation-full.mjs +0 -1
- package/dist/analysis/version.mjs +1 -1
- package/dist/cdn/script.global.js +4 -4
- package/dist/index.d.mts +151 -26
- package/dist/index.d.ts +151 -26
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +5 -3
- package/tools/reader-meta-text.d.mts +2 -0
- package/tools/reader-meta-text.mjs +26 -0
- package/tools/strip-reader-meta.d.mts +33 -0
- package/tools/strip-reader-meta.mjs +131 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/low-events/grouped-input-tracker.ts
|
|
2
2
|
import { InputChangeRecorder } from "./input-change-recorder.mjs";
|
|
3
|
-
import { InputPasteObserver } from "
|
|
3
|
+
import { InputPasteObserver } from "../readers/input-paste.mjs";
|
|
4
|
+
import { observeInputField, readFocusedField, readInputGroupValueLength } from "../readers/input.mjs";
|
|
5
|
+
import { listenWindow } from "../readers/page.mjs";
|
|
4
6
|
var LowEventGroupedInputTracker = class {
|
|
5
7
|
constructor(logger, fields, sink) {
|
|
6
8
|
this.logger = logger;
|
|
@@ -13,6 +15,27 @@ var LowEventGroupedInputTracker = class {
|
|
|
13
15
|
sink.reserveCaptureSeq
|
|
14
16
|
);
|
|
15
17
|
this.paste = new InputPasteObserver(
|
|
18
|
+
{
|
|
19
|
+
key: "dom:input.paste",
|
|
20
|
+
title: "Paste into tracked input fields",
|
|
21
|
+
accessNote: "paste events on the input elements the integration passes to Observe; pasted values never leave the reader",
|
|
22
|
+
group: "Input interaction",
|
|
23
|
+
origin: "observe-external",
|
|
24
|
+
fields: [
|
|
25
|
+
{
|
|
26
|
+
path: "event.paste",
|
|
27
|
+
label: "Paste into the field",
|
|
28
|
+
exposure: "presence",
|
|
29
|
+
transform: { note: "trusted paste events only" }
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
path: "value",
|
|
33
|
+
label: "Length of the pasted text",
|
|
34
|
+
exposure: "size",
|
|
35
|
+
transform: { note: "inserted length only; values are compared in memory and discarded" }
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
16
39
|
this.inputs,
|
|
17
40
|
logger,
|
|
18
41
|
(ts, _inserted, captureSeq) => {
|
|
@@ -32,35 +55,115 @@ var LowEventGroupedInputTracker = class {
|
|
|
32
55
|
);
|
|
33
56
|
this.unregisterInputs = sink.registerInputs?.(this.inputs, () => this.flushPending());
|
|
34
57
|
this.capturePrefill();
|
|
58
|
+
const guard = (_name, run) => this.safe(run);
|
|
35
59
|
for (const input of this.inputs) {
|
|
36
|
-
this.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
this.listeners.push(
|
|
61
|
+
observeInputField(
|
|
62
|
+
{
|
|
63
|
+
key: "dom:input.events",
|
|
64
|
+
title: "Interaction with tracked input fields",
|
|
65
|
+
accessNote: "focus, blur, pointerdown, pointerup, click, input and keyup events on the input elements the integration passes to Observe, reduced to booleans and identities",
|
|
66
|
+
group: "Input interaction",
|
|
67
|
+
origin: "observe-external",
|
|
68
|
+
fields: [
|
|
69
|
+
{ path: "event.focus", label: "Field selected", exposure: "presence" },
|
|
70
|
+
{
|
|
71
|
+
path: "event.focus.relatedTarget",
|
|
72
|
+
label: "Whether focus moved between fields of the same group",
|
|
73
|
+
exposure: "computed",
|
|
74
|
+
transform: { note: "only whether focus moves within the group" }
|
|
75
|
+
},
|
|
76
|
+
{ path: "event.blur", label: "Field left", exposure: "presence" },
|
|
77
|
+
{ path: "event.pointerdown", label: "Pointer pressed on the field", exposure: "presence" },
|
|
78
|
+
{ path: "event.pointerup", label: "Pointer released on the field", exposure: "presence" },
|
|
79
|
+
{ path: "event.click", label: "Click on the field", exposure: "presence" },
|
|
80
|
+
{ path: "event.input", label: "Typing in the field", exposure: "presence" },
|
|
81
|
+
{
|
|
82
|
+
path: "event.input.isComposing",
|
|
83
|
+
label: "Whether text is being composed with an input method",
|
|
84
|
+
exposure: "enum",
|
|
85
|
+
transform: { values: [true, false] }
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
path: "event.keyup.key",
|
|
89
|
+
label: "Escape key pressed",
|
|
90
|
+
exposure: "enum",
|
|
91
|
+
transform: { values: ["Escape", "other"] }
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
input,
|
|
96
|
+
{
|
|
97
|
+
input: (composing, event) => {
|
|
98
|
+
if (this.paste.handlesInput(event)) return;
|
|
99
|
+
this.composing ||= composing;
|
|
100
|
+
if (this.changeTimer !== null) return;
|
|
101
|
+
this.changeTime = Date.now();
|
|
102
|
+
this.changeSeq = sink.reserveCaptureSeq?.();
|
|
103
|
+
this.changeTimer = setTimeout(() => this.safe(() => this.flushChanges()), 0);
|
|
104
|
+
},
|
|
105
|
+
focus: (relatedTarget) => {
|
|
106
|
+
if (this.contains(relatedTarget)) return;
|
|
107
|
+
this.emit("focus");
|
|
108
|
+
},
|
|
109
|
+
blur: (relatedTarget) => {
|
|
110
|
+
if (this.contains(relatedTarget)) return;
|
|
111
|
+
this.flushPending();
|
|
112
|
+
this.emit("blur");
|
|
113
|
+
},
|
|
114
|
+
click: () => this.emit("click"),
|
|
115
|
+
pointerdown: () => this.emit("pointerdown"),
|
|
116
|
+
pointerup: () => this.emit("pointerup"),
|
|
117
|
+
keyupEscape: () => this.emit("keyup-escape")
|
|
118
|
+
},
|
|
119
|
+
guard,
|
|
120
|
+
["input", "focus", "blur", "click", "pointerdown", "pointerup", "keyup"]
|
|
121
|
+
)
|
|
122
|
+
);
|
|
57
123
|
}
|
|
58
124
|
if (typeof window !== "undefined")
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
125
|
+
this.listeners.push(
|
|
126
|
+
listenWindow(
|
|
127
|
+
{
|
|
128
|
+
key: "page:lifecycle.pagehide",
|
|
129
|
+
title: "Leaving the page",
|
|
130
|
+
accessNote: "pagehide event on window",
|
|
131
|
+
group: "Page lifecycle",
|
|
132
|
+
origin: "observe-external",
|
|
133
|
+
fields: [
|
|
134
|
+
{
|
|
135
|
+
path: "event.pagehide",
|
|
136
|
+
label: "Leaving the page",
|
|
137
|
+
exposure: "presence",
|
|
138
|
+
transform: { note: "flushes pending input low events on unload" }
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"pagehide",
|
|
143
|
+
(_event) => this.safe(() => {
|
|
144
|
+
this.flushPending();
|
|
145
|
+
sink.flushKeepalive();
|
|
146
|
+
})
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
if (typeof document !== "undefined" && readFocusedField(
|
|
150
|
+
{
|
|
151
|
+
key: "dom:input.focused",
|
|
152
|
+
title: "Whether a tracked input field has focus",
|
|
153
|
+
accessNote: "document.activeElement compared with the passed input elements",
|
|
154
|
+
group: "Input interaction",
|
|
155
|
+
origin: "observe-external",
|
|
156
|
+
fields: [
|
|
157
|
+
{
|
|
158
|
+
path: "focused",
|
|
159
|
+
label: "Whether the field is selected",
|
|
160
|
+
exposure: "enum",
|
|
161
|
+
transform: { values: [true, false] }
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
this.inputs
|
|
166
|
+
)) {
|
|
64
167
|
this.emit("focus");
|
|
65
168
|
}
|
|
66
169
|
}
|
|
@@ -78,7 +181,24 @@ var LowEventGroupedInputTracker = class {
|
|
|
78
181
|
return this.inputs.some((field) => field === target);
|
|
79
182
|
}
|
|
80
183
|
length() {
|
|
81
|
-
return
|
|
184
|
+
return readInputGroupValueLength(
|
|
185
|
+
{
|
|
186
|
+
key: "dom:input.content",
|
|
187
|
+
title: "Length of the text in tracked input fields",
|
|
188
|
+
accessNote: "input value length only; the value itself does not leave the reader",
|
|
189
|
+
group: "Input interaction",
|
|
190
|
+
origin: "observe-external",
|
|
191
|
+
fields: [
|
|
192
|
+
{
|
|
193
|
+
path: "value.length",
|
|
194
|
+
label: "Length of the entered text",
|
|
195
|
+
exposure: "size",
|
|
196
|
+
transform: { note: "summed over the fields of a group" }
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
this.inputs
|
|
201
|
+
);
|
|
82
202
|
}
|
|
83
203
|
safe(action) {
|
|
84
204
|
try {
|
|
@@ -87,11 +207,6 @@ var LowEventGroupedInputTracker = class {
|
|
|
87
207
|
this.logger.error("Failed to observe grouped input", error);
|
|
88
208
|
}
|
|
89
209
|
}
|
|
90
|
-
listen(target, type, handler) {
|
|
91
|
-
const wrapped = (event) => this.safe(() => handler(event));
|
|
92
|
-
target.addEventListener(type, wrapped);
|
|
93
|
-
this.listeners.push(() => target.removeEventListener(type, wrapped));
|
|
94
|
-
}
|
|
95
210
|
cancelChange() {
|
|
96
211
|
if (this.changeTimer !== null) clearTimeout(this.changeTimer);
|
|
97
212
|
this.changeTimer = null;
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
// src/low-events/input-tracker.ts
|
|
2
2
|
import { InputChangeRecorder } from "./input-change-recorder.mjs";
|
|
3
|
-
import { InputPasteObserver } from "
|
|
3
|
+
import { InputPasteObserver } from "../readers/input-paste.mjs";
|
|
4
|
+
import { observeInputField, readFocusedField, readInputContentLength } from "../readers/input.mjs";
|
|
5
|
+
import { listenWindow } from "../readers/page.mjs";
|
|
4
6
|
import { readPasswordManagerDomSignals } from "../readers/password-manager-dom.mjs";
|
|
5
7
|
var MOUNT_PROBE_DELAY_MS = 500;
|
|
6
8
|
var FOCUS_PROBE_DELAY_MS = 250;
|
|
7
9
|
function fieldContentLength(field) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
return readInputContentLength(
|
|
11
|
+
{
|
|
12
|
+
key: "dom:input.content",
|
|
13
|
+
title: "Length of the text in tracked input fields",
|
|
14
|
+
accessNote: "input value length only; the value itself does not leave the reader",
|
|
15
|
+
group: "Input interaction",
|
|
16
|
+
origin: "observe-external",
|
|
17
|
+
fields: [
|
|
18
|
+
{ path: "value.length", label: "Length of the entered text", exposure: "size" },
|
|
19
|
+
{
|
|
20
|
+
path: "checked",
|
|
21
|
+
label: "Whether a checkbox or option is selected",
|
|
22
|
+
exposure: "enum",
|
|
23
|
+
transform: { values: [true, false], note: "checkbox and radio only" }
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
field
|
|
28
|
+
);
|
|
10
29
|
}
|
|
11
30
|
var LowEventInputTracker = class {
|
|
12
31
|
constructor(logger, inputField, sink) {
|
|
@@ -20,6 +39,27 @@ var LowEventInputTracker = class {
|
|
|
20
39
|
sink.reserveCaptureSeq
|
|
21
40
|
);
|
|
22
41
|
this.pasteObserver = new InputPasteObserver(
|
|
42
|
+
{
|
|
43
|
+
key: "dom:input.paste",
|
|
44
|
+
title: "Paste into tracked input fields",
|
|
45
|
+
accessNote: "paste events on the input elements the integration passes to Observe; pasted values never leave the reader",
|
|
46
|
+
group: "Input interaction",
|
|
47
|
+
origin: "observe-external",
|
|
48
|
+
fields: [
|
|
49
|
+
{
|
|
50
|
+
path: "event.paste",
|
|
51
|
+
label: "Paste into the field",
|
|
52
|
+
exposure: "presence",
|
|
53
|
+
transform: { note: "trusted paste events only" }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
path: "value",
|
|
57
|
+
label: "Length of the pasted text",
|
|
58
|
+
exposure: "size",
|
|
59
|
+
transform: { note: "inserted length only; values are compared in memory and discarded" }
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
},
|
|
23
63
|
[inputField],
|
|
24
64
|
logger,
|
|
25
65
|
(ts, _inserted, captureSeq) => {
|
|
@@ -36,27 +76,13 @@ var LowEventInputTracker = class {
|
|
|
36
76
|
},
|
|
37
77
|
sink.reserveCaptureSeq
|
|
38
78
|
);
|
|
39
|
-
this.boundHandlers = {
|
|
40
|
-
focus: this.wrapHandler("focus", () => this.handleFocus()),
|
|
41
|
-
blur: this.wrapHandler("blur", () => this.handleBlur()),
|
|
42
|
-
pointerdown: this.wrapHandler("pointerdown", () => this.enqueueNonInputEvent("pointerdown")),
|
|
43
|
-
pointerup: this.wrapHandler("pointerup", () => this.enqueueNonInputEvent("pointerup")),
|
|
44
|
-
click: this.wrapHandler("click", () => this.enqueueNonInputEvent("click")),
|
|
45
|
-
input: (event) => {
|
|
46
|
-
try {
|
|
47
|
-
this.handleInput(event);
|
|
48
|
-
} catch (error) {
|
|
49
|
-
this.logger.error("Failed to observe input", error);
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
keyup: this.wrapKeyboardHandler("keyup", (event) => this.handleKeyUp(event)),
|
|
53
|
-
pageHide: this.wrapHandler("pagehide", () => this.flushForTeardown())
|
|
54
|
-
};
|
|
55
79
|
this.unregisterInputs = sink.registerInputs?.([inputField], () => this.flushPending());
|
|
56
80
|
this.capturePrefill();
|
|
57
81
|
this.attach();
|
|
58
82
|
}
|
|
59
83
|
unregisterInputs;
|
|
84
|
+
removeFieldListeners;
|
|
85
|
+
removePageHide;
|
|
60
86
|
changes;
|
|
61
87
|
pasteObserver;
|
|
62
88
|
emittedSignals = /* @__PURE__ */ new Set();
|
|
@@ -64,7 +90,6 @@ var LowEventInputTracker = class {
|
|
|
64
90
|
mountProbeTimer = null;
|
|
65
91
|
focusProbeTimer = null;
|
|
66
92
|
destroyed = false;
|
|
67
|
-
boundHandlers;
|
|
68
93
|
destroy() {
|
|
69
94
|
if (this.destroyed) {
|
|
70
95
|
return;
|
|
@@ -89,18 +114,93 @@ var LowEventInputTracker = class {
|
|
|
89
114
|
}
|
|
90
115
|
attach() {
|
|
91
116
|
const input = this.inputField;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
this.removeFieldListeners = observeInputField(
|
|
118
|
+
{
|
|
119
|
+
key: "dom:input.events",
|
|
120
|
+
title: "Interaction with tracked input fields",
|
|
121
|
+
accessNote: "focus, blur, pointerdown, pointerup, click, input and keyup events on the input elements the integration passes to Observe, reduced to booleans and identities",
|
|
122
|
+
group: "Input interaction",
|
|
123
|
+
origin: "observe-external",
|
|
124
|
+
fields: [
|
|
125
|
+
{ path: "event.focus", label: "Field selected", exposure: "presence" },
|
|
126
|
+
{ path: "event.blur", label: "Field left", exposure: "presence" },
|
|
127
|
+
{ path: "event.pointerdown", label: "Pointer pressed on the field", exposure: "presence" },
|
|
128
|
+
{ path: "event.pointerup", label: "Pointer released on the field", exposure: "presence" },
|
|
129
|
+
{ path: "event.click", label: "Click on the field", exposure: "presence" },
|
|
130
|
+
{ path: "event.input", label: "Typing in the field", exposure: "presence" },
|
|
131
|
+
{
|
|
132
|
+
path: "event.input.isComposing",
|
|
133
|
+
label: "Whether text is being composed with an input method",
|
|
134
|
+
exposure: "enum",
|
|
135
|
+
transform: { values: [true, false] }
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
path: "event.keyup.key",
|
|
139
|
+
label: "Escape key pressed",
|
|
140
|
+
exposure: "enum",
|
|
141
|
+
transform: { values: ["Escape", "other"] }
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
input,
|
|
146
|
+
{
|
|
147
|
+
focus: () => this.handleFocus(),
|
|
148
|
+
blur: () => this.handleBlur(),
|
|
149
|
+
pointerdown: () => this.enqueueNonInputEvent("pointerdown"),
|
|
150
|
+
pointerup: () => this.enqueueNonInputEvent("pointerup"),
|
|
151
|
+
click: () => this.enqueueNonInputEvent("click"),
|
|
152
|
+
input: (composing, event) => this.handleInput(event, composing),
|
|
153
|
+
keyupEscape: () => this.enqueueNonInputEvent("keyup-escape")
|
|
154
|
+
},
|
|
155
|
+
(name, run) => {
|
|
156
|
+
try {
|
|
157
|
+
run();
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (name === "input") this.logger.error("Failed to observe input", error);
|
|
160
|
+
else this.logger.error(`Failed to handle low event "${name}"`, error);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
);
|
|
99
164
|
if (typeof window !== "undefined") {
|
|
100
|
-
|
|
165
|
+
this.removePageHide = listenWindow(
|
|
166
|
+
{
|
|
167
|
+
key: "page:lifecycle.pagehide",
|
|
168
|
+
title: "Leaving the page",
|
|
169
|
+
accessNote: "pagehide event on window",
|
|
170
|
+
group: "Page lifecycle",
|
|
171
|
+
origin: "observe-external",
|
|
172
|
+
fields: [
|
|
173
|
+
{
|
|
174
|
+
path: "event.pagehide",
|
|
175
|
+
label: "Leaving the page",
|
|
176
|
+
exposure: "presence",
|
|
177
|
+
transform: { note: "flushes pending input low events on unload" }
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
"pagehide",
|
|
182
|
+
this.wrapHandler("pagehide", () => this.flushForTeardown())
|
|
183
|
+
);
|
|
101
184
|
}
|
|
102
185
|
if (typeof document !== "undefined") {
|
|
103
|
-
if (
|
|
186
|
+
if (readFocusedField(
|
|
187
|
+
{
|
|
188
|
+
key: "dom:input.focused",
|
|
189
|
+
title: "Whether a tracked input field has focus",
|
|
190
|
+
accessNote: "document.activeElement compared with the passed input elements",
|
|
191
|
+
group: "Input interaction",
|
|
192
|
+
origin: "observe-external",
|
|
193
|
+
fields: [
|
|
194
|
+
{
|
|
195
|
+
path: "focused",
|
|
196
|
+
label: "Whether the field is selected",
|
|
197
|
+
exposure: "enum",
|
|
198
|
+
transform: { values: [true, false] }
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
[input]
|
|
203
|
+
)) {
|
|
104
204
|
this.handleFocus();
|
|
105
205
|
}
|
|
106
206
|
}
|
|
@@ -109,16 +209,9 @@ var LowEventInputTracker = class {
|
|
|
109
209
|
}
|
|
110
210
|
}
|
|
111
211
|
detach() {
|
|
112
|
-
|
|
113
|
-
input.removeEventListener("focus", this.boundHandlers.focus);
|
|
114
|
-
input.removeEventListener("blur", this.boundHandlers.blur);
|
|
115
|
-
input.removeEventListener("pointerdown", this.boundHandlers.pointerdown);
|
|
116
|
-
input.removeEventListener("pointerup", this.boundHandlers.pointerup);
|
|
117
|
-
input.removeEventListener("click", this.boundHandlers.click);
|
|
118
|
-
input.removeEventListener("input", this.boundHandlers.input);
|
|
119
|
-
input.removeEventListener("keyup", this.boundHandlers.keyup);
|
|
212
|
+
this.removeFieldListeners?.();
|
|
120
213
|
if (typeof window !== "undefined") {
|
|
121
|
-
|
|
214
|
+
this.removePageHide?.();
|
|
122
215
|
}
|
|
123
216
|
}
|
|
124
217
|
pushLow = (low) => {
|
|
@@ -129,9 +222,14 @@ var LowEventInputTracker = class {
|
|
|
129
222
|
if (typeof __CBO_DATA_PMD__ === "boolean" ? __CBO_DATA_PMD__ : this.sink.passwordManagerDomScan?.() !== false) {
|
|
130
223
|
const matches = readPasswordManagerDomSignals({
|
|
131
224
|
key: "dom:password-managers.dom-signals",
|
|
225
|
+
title: "Password manager traces in the page",
|
|
226
|
+
accessNote: "DOM markers that password manager extensions insert (attributes, elements, styles)",
|
|
227
|
+
group: "Password manager detection",
|
|
228
|
+
origin: "observe-external",
|
|
132
229
|
fields: [
|
|
133
230
|
{
|
|
134
231
|
path: "signals[]",
|
|
232
|
+
label: "Password manager traces found",
|
|
135
233
|
exposure: "enum",
|
|
136
234
|
transform: { values: ["pa-1", "pa-2", "pa-3", "pa-4", "pa-5", "pa-6"] }
|
|
137
235
|
}
|
|
@@ -179,19 +277,9 @@ var LowEventInputTracker = class {
|
|
|
179
277
|
this.pasteObserver.flush();
|
|
180
278
|
this.enqueueNonInputEvent("blur");
|
|
181
279
|
}
|
|
182
|
-
handleInput(event) {
|
|
280
|
+
handleInput(event, composing) {
|
|
183
281
|
if (this.pasteObserver.handlesInput(event)) return;
|
|
184
|
-
this.changes.record(
|
|
185
|
-
fieldContentLength(this.inputField),
|
|
186
|
-
Date.now(),
|
|
187
|
-
event.isComposing || event.inputType === "insertCompositionText"
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
handleKeyUp(event) {
|
|
191
|
-
if (event.key !== "Escape") {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
this.enqueueNonInputEvent("keyup-escape");
|
|
282
|
+
this.changes.record(fieldContentLength(this.inputField), Date.now(), composing);
|
|
195
283
|
}
|
|
196
284
|
flushForTeardown() {
|
|
197
285
|
this.pasteObserver.flush();
|
|
@@ -207,15 +295,6 @@ var LowEventInputTracker = class {
|
|
|
207
295
|
}
|
|
208
296
|
};
|
|
209
297
|
}
|
|
210
|
-
wrapKeyboardHandler(name, fn) {
|
|
211
|
-
return (event) => {
|
|
212
|
-
try {
|
|
213
|
-
fn(event);
|
|
214
|
-
} catch (error) {
|
|
215
|
-
this.logger.error(`Failed to handle low event "${name}"`, error);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
298
|
};
|
|
220
299
|
export {
|
|
221
300
|
LowEventInputTracker,
|