@protontech/autofill 0.0.22991789 → 0.0.33690782
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/constants/features.d.ts +1 -0
- package/constants/features.js +1 -0
- package/constants/heuristics.d.ts +5 -4
- package/constants/heuristics.js +5 -10
- package/constants/selectors.d.ts +13 -7
- package/constants/selectors.js +29 -17
- package/debug.d.ts +24 -1
- package/debug.js +15 -13
- package/dictionary/generate.js +30 -21
- package/dictionary/generated/dictionary.d.ts +18 -4
- package/dictionary/generated/dictionary.js +31 -17
- package/dictionary/source/dictionary.d.ts +4 -3
- package/dictionary/source/dictionary.js +155 -89
- package/dictionary/source/patterns.js +2 -2
- package/features/feature.d.ts +17 -0
- package/features/feature.js +72 -0
- package/features/feature.spec.d.ts +1 -0
- package/features/feature.spec.js +55 -0
- package/features/v1/abstract.field.d.ts +20401 -0
- package/features/v1/abstract.field.js +95 -0
- package/features/v1/abstract.form.d.ts +1226 -0
- package/features/v1/abstract.form.js +336 -0
- package/features/v1/field.email.d.ts +62 -0
- package/features/v1/field.email.js +27 -0
- package/features/v1/field.otp.d.ts +142 -0
- package/features/v1/field.otp.js +105 -0
- package/features/v1/field.password.d.ts +162 -0
- package/features/v1/field.password.js +81 -0
- package/features/v1/field.username-hidden.d.ts +62 -0
- package/features/v1/field.username-hidden.js +25 -0
- package/features/v1/field.username.d.ts +72 -0
- package/features/v1/field.username.js +31 -0
- package/features/v1/index.d.ts +4427 -0
- package/features/v1/index.js +22 -0
- package/features/v1/index.spec.d.ts +1 -0
- package/features/v1/index.spec.js +30 -0
- package/index.d.ts +5 -2
- package/index.js +10 -3
- package/models/perceptron/index.d.ts +2 -0
- package/models/perceptron/index.js +27 -0
- package/models/perceptron/params/email-model.json +53 -0
- package/models/perceptron/params/login-model.json +465 -0
- package/models/perceptron/params/new-password-model.json +133 -0
- package/models/perceptron/params/otp-model.json +117 -0
- package/models/perceptron/params/password-change-model.json +465 -0
- package/models/perceptron/params/password-model.json +133 -0
- package/models/perceptron/params/recovery-model.json +465 -0
- package/models/perceptron/params/register-model.json +465 -0
- package/models/perceptron/params/username-hidden-model.json +53 -0
- package/models/perceptron/params/username-model.json +61 -0
- package/models/prod_20240829/index.d.ts +2 -0
- package/models/prod_20240829/index.js +27 -0
- package/models/prod_20240829/params/email-model.json +45 -0
- package/models/prod_20240829/params/login-model.json +421 -0
- package/models/prod_20240829/params/new-password-model.json +125 -0
- package/models/prod_20240829/params/otp-model.json +153 -0
- package/models/prod_20240829/params/password-change-model.json +421 -0
- package/models/prod_20240829/params/password-model.json +125 -0
- package/models/prod_20240829/params/recovery-model.json +421 -0
- package/models/prod_20240829/params/register-model.json +421 -0
- package/models/prod_20240829/params/username-hidden-model.json +41 -0
- package/models/prod_20240829/params/username-model.json +45 -0
- package/models/random_forest/index.d.ts +2 -0
- package/models/random_forest/index.js +27 -0
- package/models/random_forest/params/email-model.json +1456 -0
- package/models/random_forest/params/login-model.json +4194 -0
- package/models/random_forest/params/new-password-model.json +1448 -0
- package/models/random_forest/params/otp-model.json +2004 -0
- package/models/random_forest/params/password-change-model.json +1422 -0
- package/models/random_forest/params/password-model.json +1292 -0
- package/models/random_forest/params/recovery-model.json +2754 -0
- package/models/random_forest/params/register-model.json +3678 -0
- package/models/random_forest/params/username-hidden-model.json +1108 -0
- package/models/random_forest/params/username-model.json +1052 -0
- package/models/v1/index.d.ts +2 -0
- package/models/v1/index.js +35 -0
- package/package.json +14 -15
- package/rules/v1/index.d.ts +3 -0
- package/rules/v1/index.js +69 -0
- package/rulesets.d.ts +2 -2
- package/rulesets.js +11 -10
- package/types/index.d.ts +72 -17
- package/types/index.js +35 -2
- package/utils/attributes.js +1 -1
- package/utils/clustering.js +18 -5
- package/utils/credit-card.d.ts +32 -0
- package/utils/credit-card.js +259 -0
- package/utils/credit-card.samples.spec.d.ts +1 -0
- package/utils/credit-card.samples.spec.js +452 -0
- package/utils/credit-card.spec.d.ts +1 -0
- package/utils/credit-card.spec.js +296 -0
- package/utils/dom.d.ts +3 -2
- package/utils/dom.js +12 -7
- package/utils/exclusion.d.ts +1 -0
- package/utils/exclusion.js +22 -10
- package/utils/extract.d.ts +1 -0
- package/utils/extract.js +26 -7
- package/utils/fathom.d.ts +10 -23
- package/utils/fathom.js +7 -12
- package/utils/field.d.ts +12 -4
- package/utils/field.js +25 -14
- package/utils/flags.d.ts +9 -3
- package/utils/flags.js +27 -9
- package/utils/form.d.ts +16 -5
- package/utils/form.js +35 -14
- package/utils/identity.d.ts +12 -21
- package/utils/identity.js +66 -41
- package/utils/identity.samples.spec.d.ts +1 -0
- package/utils/identity.samples.spec.js +28 -0
- package/utils/iframe.d.ts +2 -0
- package/utils/iframe.js +22 -0
- package/utils/overrides.d.ts +19 -0
- package/utils/overrides.js +40 -0
- package/utils/prepass.js +6 -4
- package/utils/re.d.ts +19 -4
- package/utils/re.js +22 -7
- package/utils/re.spec.d.ts +1 -0
- package/utils/re.spec.js +62 -0
- package/utils/shadow-dom.d.ts +8 -0
- package/utils/shadow-dom.js +53 -0
- package/utils/shadow-dom.spec.d.ts +1 -0
- package/utils/shadow-dom.spec.js +215 -0
- package/utils/visible.d.ts +3 -2
- package/utils/visible.js +42 -22
- package/cli.d.ts +0 -2
- package/cli.js +0 -128
- package/features/abstract.field.d.ts +0 -123
- package/features/abstract.field.js +0 -63
- package/features/abstract.form.d.ts +0 -98
- package/features/abstract.form.js +0 -281
- package/features/field.email.d.ts +0 -18
- package/features/field.email.js +0 -43
- package/features/field.otp.d.ts +0 -36
- package/features/field.otp.js +0 -116
- package/features/field.password.d.ts +0 -35
- package/features/field.password.js +0 -104
- package/features/field.username-hidden.d.ts +0 -15
- package/features/field.username-hidden.js +0 -40
- package/features/field.username.d.ts +0 -16
- package/features/field.username.js +0 -41
- package/features/form.combined.d.ts +0 -1
- package/features/form.combined.js +0 -6
- package/trainees/field.email.d.ts +0 -2
- package/trainees/field.email.js +0 -16
- package/trainees/field.identity.d.ts +0 -2
- package/trainees/field.identity.js +0 -9
- package/trainees/field.otp.d.ts +0 -2
- package/trainees/field.otp.js +0 -16
- package/trainees/field.password.current.d.ts +0 -2
- package/trainees/field.password.current.js +0 -16
- package/trainees/field.password.new.d.ts +0 -2
- package/trainees/field.password.new.js +0 -16
- package/trainees/field.username-hidden.d.ts +0 -2
- package/trainees/field.username-hidden.js +0 -22
- package/trainees/field.username.d.ts +0 -2
- package/trainees/field.username.js +0 -16
- package/trainees/form.login.d.ts +0 -2
- package/trainees/form.login.js +0 -16
- package/trainees/form.noop.d.ts +0 -1
- package/trainees/form.noop.js +0 -7
- package/trainees/form.password-change.d.ts +0 -2
- package/trainees/form.password-change.js +0 -16
- package/trainees/form.recovery.d.ts +0 -2
- package/trainees/form.recovery.js +0 -16
- package/trainees/form.register.d.ts +0 -2
- package/trainees/form.register.js +0 -16
- package/trainees/index.d.ts +0 -9
- package/trainees/index.js +0 -72
- package/trainees/results/result.email.d.ts +0 -2
- package/trainees/results/result.email.js +0 -17
- package/trainees/results/result.login.d.ts +0 -2
- package/trainees/results/result.login.js +0 -110
- package/trainees/results/result.new-password.d.ts +0 -2
- package/trainees/results/result.new-password.js +0 -36
- package/trainees/results/result.otp.d.ts +0 -2
- package/trainees/results/result.otp.js +0 -43
- package/trainees/results/result.password-change.d.ts +0 -2
- package/trainees/results/result.password-change.js +0 -110
- package/trainees/results/result.password.d.ts +0 -2
- package/trainees/results/result.password.js +0 -36
- package/trainees/results/result.recovery.d.ts +0 -2
- package/trainees/results/result.recovery.js +0 -110
- package/trainees/results/result.register.d.ts +0 -2
- package/trainees/results/result.register.js +0 -110
- package/trainees/results/result.username-hidden.d.ts +0 -2
- package/trainees/results/result.username-hidden.js +0 -15
- package/trainees/results/result.username.d.ts +0 -2
- package/trainees/results/result.username.js +0 -16
- package/utils/memoize.d.ts +0 -5
- package/utils/memoize.js +0 -12
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { featureProvider } from "../../features/v1";
|
|
2
|
+
import { getPerceptronForClass } from "../perceptron";
|
|
3
|
+
import { getRandomForestInferrerForClass } from "../random_forest";
|
|
4
|
+
const perceptronModelProvider = {
|
|
5
|
+
field: { featureComputer: featureProvider.field },
|
|
6
|
+
form: { featureComputer: featureProvider.form },
|
|
7
|
+
"new-password": { model: getPerceptronForClass("new-password"), featureComputer: featureProvider["new-password"] },
|
|
8
|
+
"password-change": { model: getPerceptronForClass("password-change"), featureComputer: featureProvider["password-change"] },
|
|
9
|
+
"username-hidden": { model: getPerceptronForClass("username-hidden"), featureComputer: featureProvider["username-hidden"] },
|
|
10
|
+
email: { model: getPerceptronForClass("email"), featureComputer: featureProvider.email },
|
|
11
|
+
login: { model: getPerceptronForClass("login"), featureComputer: featureProvider.login },
|
|
12
|
+
otp: { model: getPerceptronForClass("otp"), featureComputer: featureProvider.otp },
|
|
13
|
+
password: { model: getPerceptronForClass("password"), featureComputer: featureProvider.password },
|
|
14
|
+
recovery: { model: getPerceptronForClass("recovery"), featureComputer: featureProvider.recovery },
|
|
15
|
+
register: { model: getPerceptronForClass("register"), featureComputer: featureProvider.register },
|
|
16
|
+
username: { model: getPerceptronForClass("username"), featureComputer: featureProvider.username },
|
|
17
|
+
};
|
|
18
|
+
const randomForestModelProvider = {
|
|
19
|
+
field: { featureComputer: featureProvider.field },
|
|
20
|
+
form: { featureComputer: featureProvider.form },
|
|
21
|
+
"new-password": { model: getRandomForestInferrerForClass("new-password"), featureComputer: featureProvider["new-password"] },
|
|
22
|
+
"password-change": { model: getRandomForestInferrerForClass("password-change"), featureComputer: featureProvider["password-change"] },
|
|
23
|
+
"username-hidden": { model: getRandomForestInferrerForClass("username-hidden"), featureComputer: featureProvider["username-hidden"] },
|
|
24
|
+
email: { model: getRandomForestInferrerForClass("email"), featureComputer: featureProvider.email },
|
|
25
|
+
login: { model: getRandomForestInferrerForClass("login"), featureComputer: featureProvider.login },
|
|
26
|
+
otp: { model: getRandomForestInferrerForClass("otp"), featureComputer: featureProvider.otp },
|
|
27
|
+
password: { model: getRandomForestInferrerForClass("password"), featureComputer: featureProvider.password },
|
|
28
|
+
recovery: { model: getRandomForestInferrerForClass("recovery"), featureComputer: featureProvider.recovery },
|
|
29
|
+
register: { model: getRandomForestInferrerForClass("register"), featureComputer: featureProvider.register },
|
|
30
|
+
username: { model: getRandomForestInferrerForClass("username"), featureComputer: featureProvider.username },
|
|
31
|
+
};
|
|
32
|
+
export const ModelProviders = {
|
|
33
|
+
dev_perceptron: perceptronModelProvider,
|
|
34
|
+
dev_randomForest: randomForestModelProvider,
|
|
35
|
+
};
|
package/package.json
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protontech/autofill",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.33690782",
|
|
4
4
|
"private": false,
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@protontech/fathom": "0.0.
|
|
7
|
-
"@
|
|
8
|
-
"@types/regexgen": "^1.3.3",
|
|
9
|
-
"commander": "^13.1.0",
|
|
10
|
-
"prettier": "^3.5.1",
|
|
11
|
-
"regexgen": "^1.3.0"
|
|
6
|
+
"@protontech/fathom": "0.0.33690782",
|
|
7
|
+
"@protontech/ml-inference": "0.0.33690782"
|
|
12
8
|
},
|
|
13
9
|
"devDependencies": {
|
|
14
|
-
"@rollup/plugin-commonjs": "^28.0.2",
|
|
15
|
-
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
16
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
17
|
-
"@rollup/plugin-typescript": "^12.1.2",
|
|
18
10
|
"@types/jest": "^29.5.14",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
11
|
+
"@types/node": "^22.13.4",
|
|
12
|
+
"@types/regexgen": "^1.3.3",
|
|
13
|
+
"jest-cli": "^30.2.0",
|
|
14
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
15
|
+
"jest-junit": "^16.0.0",
|
|
16
|
+
"prettier": "^3.5.1",
|
|
17
|
+
"regexgen": "^1.3.0",
|
|
18
|
+
"ts-node": "^10.9.2",
|
|
19
|
+
"tsconfig-paths": "^4.2.0",
|
|
22
20
|
"tslib": "^2.8.1"
|
|
23
21
|
},
|
|
24
22
|
"license": "MPL-2.0",
|
|
25
23
|
"author": "Edvin Candon <edvin.candon@proton.ch>",
|
|
26
24
|
"contributors": [
|
|
27
25
|
"Guðmundur Heimisson <gudmundur.heimisson@proton.ch>"
|
|
28
|
-
]
|
|
26
|
+
],
|
|
27
|
+
"type": "module"
|
|
29
28
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { AnyRule, DetectionClass, FeatureProvider } from "../../types";
|
|
2
|
+
export declare const getBaseRules: (featureProvider: FeatureProvider) => readonly [import("@protontech/fathom").OutwardRule | import("@protontech/fathom").InwardRule, import("@protontech/fathom").OutwardRule | import("@protontech/fathom").InwardRule, ...(import("@protontech/fathom").OutwardRule | import("@protontech/fathom").InwardRule)[], import("@protontech/fathom").OutwardRule | import("@protontech/fathom").InwardRule];
|
|
3
|
+
export declare const getRulesProvider: (featureProvider: FeatureProvider) => Record<DetectionClass, readonly AnyRule[]>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { dom, out, rule, type } from "@protontech/fathom";
|
|
2
|
+
import { FEATURE_SEPARATOR } from "../../constants/features";
|
|
3
|
+
import { formCandidateSelector } from "../../constants/selectors";
|
|
4
|
+
import { computeFeatures, FieldType, FormType } from "../../types";
|
|
5
|
+
import { isCCInputField, isCCSelectField } from "../../utils/credit-card";
|
|
6
|
+
import { featureScore, isNoopForm, outRuleWithCache, processFieldEffect, processFormEffect, withFnodeEl } from "../../utils/fathom";
|
|
7
|
+
import { isClassifiableField, maybeEmail, maybeHiddenUsername, maybeOTP, maybePassword, maybeUsername } from "../../utils/field";
|
|
8
|
+
import { isClassifiable } from "../../utils/flags";
|
|
9
|
+
import { isIdentity } from "../../utils/identity";
|
|
10
|
+
import { overrides } from "../../utils/overrides";
|
|
11
|
+
import { isVisibleForm } from "../../utils/visible";
|
|
12
|
+
const getRulesForFieldClass = (klass, featureComputer) => [
|
|
13
|
+
rule(type(`${klass}-field`), type(klass), {}),
|
|
14
|
+
...featureComputer.features.map((feat) => rule(type(klass), featureScore(`${klass}-field`, feat), { name: `${klass}${FEATURE_SEPARATOR}${feat.name}` })),
|
|
15
|
+
...outRuleWithCache("field-candidate", klass),
|
|
16
|
+
];
|
|
17
|
+
const getRulesForFormClass = (klass, featureComputer) => [
|
|
18
|
+
rule(type("form"), type(klass), {}),
|
|
19
|
+
...featureComputer.features.map((feat) => rule(type(klass), featureScore("form", feat), { name: `${klass}${FEATURE_SEPARATOR}${feat.name}` })),
|
|
20
|
+
...outRuleWithCache("form-candidate", klass),
|
|
21
|
+
];
|
|
22
|
+
const noopRules = [
|
|
23
|
+
rule(type("form").when(isNoopForm), type(FormType.NOOP), {}),
|
|
24
|
+
...outRuleWithCache("form-candidate", FormType.NOOP, () => () => true),
|
|
25
|
+
];
|
|
26
|
+
const identityRules = [
|
|
27
|
+
rule(type("field").when(isIdentity), type("identity-field"), {}),
|
|
28
|
+
rule(type("identity-field"), type(FieldType.IDENTITY), {}),
|
|
29
|
+
...outRuleWithCache("field-candidate", FieldType.IDENTITY, () => () => true),
|
|
30
|
+
];
|
|
31
|
+
const ccRules = [
|
|
32
|
+
rule(type("field").when(isCCInputField), type("cc-field"), {}),
|
|
33
|
+
rule(type("field-candidate").when(isCCSelectField), type("cc-field"), {}),
|
|
34
|
+
rule(type("cc-field"), type(FieldType.CREDIT_CARD), {}),
|
|
35
|
+
...outRuleWithCache("field-candidate", FieldType.CREDIT_CARD, () => () => true),
|
|
36
|
+
];
|
|
37
|
+
export const getBaseRules = (featureProvider) => [
|
|
38
|
+
rule(dom(formCandidateSelector), type("form-candidate"), {}),
|
|
39
|
+
rule(dom("input"), type("field-candidate"), {}),
|
|
40
|
+
...overrides,
|
|
41
|
+
rule(type("form-candidate").when(withFnodeEl(isClassifiable)), type("form-element"), {}),
|
|
42
|
+
rule(type("form-element").when(withFnodeEl(isVisibleForm)), type("form").note((fnode) => computeFeatures(featureProvider.form, fnode)), {}),
|
|
43
|
+
rule(type("form-element"), out("form").through(processFormEffect), {}),
|
|
44
|
+
...noopRules,
|
|
45
|
+
rule(type("field-candidate").when(isClassifiableField), type("field").note((fnode) => computeFeatures(featureProvider.field, fnode)), {}),
|
|
46
|
+
rule(type("field").when(maybeUsername), type("username-field").note((fnode) => computeFeatures(featureProvider.username, fnode)), {}),
|
|
47
|
+
rule(type("field").when(maybeHiddenUsername), type("username-hidden-field").note((fnode) => computeFeatures(featureProvider["username-hidden"], fnode)), {}),
|
|
48
|
+
rule(type("field").when(maybeEmail), type("email-field").note((fnode) => computeFeatures(featureProvider.email, fnode)), {}),
|
|
49
|
+
rule(type("field").when(maybePassword), type("password-field").note((fnode) => computeFeatures(featureProvider.password, fnode)), {}),
|
|
50
|
+
rule(type("field").when(maybePassword), type("new-password-field").note((fnode) => computeFeatures(featureProvider["new-password"], fnode)), {}),
|
|
51
|
+
rule(type("field").when(maybeOTP), type("otp-field").note((fnode) => computeFeatures(featureProvider.otp, fnode)), {}),
|
|
52
|
+
...identityRules,
|
|
53
|
+
...ccRules,
|
|
54
|
+
rule(type("field"), out("field").through(processFieldEffect), {}),
|
|
55
|
+
];
|
|
56
|
+
export const getRulesProvider = (featureProvider) => {
|
|
57
|
+
return {
|
|
58
|
+
email: getRulesForFieldClass("email", featureProvider.email),
|
|
59
|
+
otp: getRulesForFieldClass("otp", featureProvider.otp),
|
|
60
|
+
password: getRulesForFieldClass("password", featureProvider.password),
|
|
61
|
+
"new-password": getRulesForFieldClass("new-password", featureProvider["new-password"]),
|
|
62
|
+
"username-hidden": getRulesForFieldClass("username-hidden", featureProvider["username-hidden"]),
|
|
63
|
+
username: getRulesForFieldClass("username", featureProvider.username),
|
|
64
|
+
login: getRulesForFormClass("login", featureProvider.login),
|
|
65
|
+
"password-change": getRulesForFormClass("password-change", featureProvider["password-change"]),
|
|
66
|
+
recovery: getRulesForFormClass("recovery", featureProvider.recovery),
|
|
67
|
+
register: getRulesForFormClass("register", featureProvider.register),
|
|
68
|
+
};
|
|
69
|
+
};
|
package/rulesets.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import type { ModelProvider } from "./types";
|
|
2
|
+
export declare const rulesetMaker: (modelProvider: ModelProvider) => import("@protontech/fathom").Ruleset;
|
package/rulesets.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { ruleset } from "@protontech/fathom";
|
|
2
|
+
import { detectionClasses } from "./types";
|
|
3
|
+
import { getBaseRules, getRulesProvider } from "./rules/v1";
|
|
4
|
+
import { prepass } from "./utils/prepass";
|
|
5
|
+
export const rulesetMaker = (modelProvider) => {
|
|
6
|
+
const featureProvider = Object.fromEntries(Object.keys(modelProvider).map((klass) => [klass, modelProvider[klass].featureComputer]));
|
|
7
|
+
const rulesProvider = getRulesProvider(featureProvider);
|
|
8
|
+
const rules = [...getBaseRules(featureProvider), ...detectionClasses.flatMap((klass) => rulesProvider[klass])];
|
|
9
|
+
const models = new Map(detectionClasses.map((klass) => [klass, modelProvider[klass].model]));
|
|
10
|
+
return ruleset(rules, models, prepass);
|
|
11
|
+
};
|
package/types/index.d.ts
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Fnode, rule } from "@protontech/fathom";
|
|
2
|
+
import type { Features, Inferrer } from "@protontech/ml-inference";
|
|
2
3
|
export type AnyRule = ReturnType<typeof rule>;
|
|
3
|
-
export type Ruleset = ReturnType<typeof ruleset>;
|
|
4
|
-
export type BoundRuleset = ReturnType<Ruleset["against"]>;
|
|
5
4
|
export type Coeff = [string, number];
|
|
6
|
-
export type
|
|
7
|
-
export type RulesetAggregation = {
|
|
8
|
-
rules: AnyRule[];
|
|
9
|
-
coeffs: Coeff[];
|
|
10
|
-
biases: Bias[];
|
|
11
|
-
};
|
|
12
|
-
export type TrainingResults = {
|
|
5
|
+
export type PerceptronParams = {
|
|
13
6
|
coeffs: Coeff[];
|
|
14
7
|
bias: number;
|
|
15
8
|
cutoff: number;
|
|
16
9
|
};
|
|
17
|
-
export type Trainee = TrainingResults & {
|
|
18
|
-
name: string;
|
|
19
|
-
getRules: () => AnyRule[];
|
|
20
|
-
};
|
|
21
10
|
export declare enum FormType {
|
|
22
11
|
LOGIN = "login",
|
|
23
12
|
NOOP = "noop",
|
|
@@ -32,7 +21,73 @@ export declare enum FieldType {
|
|
|
32
21
|
PASSWORD_CURRENT = "password",
|
|
33
22
|
PASSWORD_NEW = "new-password",
|
|
34
23
|
USERNAME = "username",
|
|
35
|
-
USERNAME_HIDDEN = "username-hidden"
|
|
24
|
+
USERNAME_HIDDEN = "username-hidden",
|
|
25
|
+
CREDIT_CARD = "credit-card"
|
|
26
|
+
}
|
|
27
|
+
export declare enum CCFieldType {
|
|
28
|
+
NAME = "cc:name",
|
|
29
|
+
FIRSTNAME = "cc:firstname",
|
|
30
|
+
LASTNAME = "cc:lastname",
|
|
31
|
+
NUMBER = "cc:number",
|
|
32
|
+
CSC = "cc:cvc",
|
|
33
|
+
EXP = "cc:exp",
|
|
34
|
+
EXP_YEAR = "cc:exp-year",
|
|
35
|
+
EXP_MONTH = "cc:exp-month"
|
|
36
|
+
}
|
|
37
|
+
export declare const ccFields: Set<string>;
|
|
38
|
+
export declare enum IdentityFieldType {
|
|
39
|
+
FULLNAME = "id:fullname",
|
|
40
|
+
FIRSTNAME = "id:firstname",
|
|
41
|
+
MIDDLENAME = "id:middlname",
|
|
42
|
+
LASTNAME = "id:lastname",
|
|
43
|
+
TELEPHONE = "id:tel",
|
|
44
|
+
ADDRESS = "id:address",
|
|
45
|
+
STATE = "id:state",
|
|
46
|
+
CITY = "id:city",
|
|
47
|
+
ZIPCODE = "id:zipcode",
|
|
48
|
+
ORGANIZATION = "id:org",
|
|
49
|
+
COUNTRY = "id:country",
|
|
50
|
+
EMAIL = "id:email"
|
|
51
|
+
}
|
|
52
|
+
export declare const identityFields: Set<string>;
|
|
53
|
+
export declare const fieldClasses: readonly ["email", "otp", "password", "new-password", "username", "username-hidden"];
|
|
54
|
+
export declare const formClasses: readonly ["login", "password-change", "recovery", "register"];
|
|
55
|
+
export declare const detectionClasses: readonly ["email", "otp", "password", "new-password", "username", "username-hidden", "login", "password-change", "recovery", "register"];
|
|
56
|
+
export declare const abstractDetectionClasses: readonly ["field", "form"];
|
|
57
|
+
export declare const modelNames: readonly ["dev_perceptron", "dev_randomForest"];
|
|
58
|
+
export type ModelName = (typeof modelNames)[number];
|
|
59
|
+
export type FormClass = (typeof formClasses)[number];
|
|
60
|
+
export type FieldClass = (typeof fieldClasses)[number];
|
|
61
|
+
export type DetectionClass = (typeof detectionClasses)[number];
|
|
62
|
+
export type HeuristicDetectionClass = (typeof abstractDetectionClasses)[number];
|
|
63
|
+
export type AbstractFeatures<T = unknown> = Record<string, AbstractFeature<T>>;
|
|
64
|
+
export interface AbstractFeature<T = unknown> extends Feature<string, T, AbstractFeatures> {
|
|
36
65
|
}
|
|
37
|
-
export
|
|
38
|
-
|
|
66
|
+
export type InferParentComputeType<P extends AbstractFeatures> = {
|
|
67
|
+
[K in keyof P as P[K]["name"]]: ReturnType<P[K]["compute"]>;
|
|
68
|
+
};
|
|
69
|
+
export type InferFeatureName<F extends AbstractFeature> = F extends Feature<infer N, unknown, AbstractFeatures> ? N : never;
|
|
70
|
+
export type InferFeatureReturnType<F extends AbstractFeature> = F extends Feature<string, infer R, AbstractFeatures> ? R : never;
|
|
71
|
+
export type Feature<N extends string, R, P extends AbstractFeatures> = {
|
|
72
|
+
name: N;
|
|
73
|
+
parents: P;
|
|
74
|
+
compute(parents: InferParentComputeType<P>, fnode: Fnode): R;
|
|
75
|
+
};
|
|
76
|
+
export type ComputedFeatures<F extends AbstractFeatures> = {
|
|
77
|
+
[K in keyof F as F[K]["name"]]: ReturnType<F[K]["compute"]>;
|
|
78
|
+
};
|
|
79
|
+
export interface FeatureComputer<F extends AbstractFeatures = AbstractFeatures> {
|
|
80
|
+
compute(fnode: Fnode): ComputedFeatures<F>;
|
|
81
|
+
features: AbstractFeature[];
|
|
82
|
+
}
|
|
83
|
+
export declare const computeFeatures: <F extends AbstractFeatures>(featureComputer: FeatureComputer<F>, fnode: Fnode) => ComputedFeatures<F>;
|
|
84
|
+
export type ModelProviderRegistry = Record<ModelName, ModelProvider>;
|
|
85
|
+
export type FeatureProvider = Record<DetectionClass | "field" | "form", FeatureComputer>;
|
|
86
|
+
export type ModelProvider = {
|
|
87
|
+
[Klass in DetectionClass | HeuristicDetectionClass]: Klass extends HeuristicDetectionClass ? {
|
|
88
|
+
featureComputer: FeatureComputer;
|
|
89
|
+
} : {
|
|
90
|
+
featureComputer: FeatureComputer;
|
|
91
|
+
model: Inferrer<Features, number>;
|
|
92
|
+
};
|
|
93
|
+
};
|
package/types/index.js
CHANGED
|
@@ -15,6 +15,39 @@ export var FieldType;
|
|
|
15
15
|
FieldType["PASSWORD_NEW"] = "new-password";
|
|
16
16
|
FieldType["USERNAME"] = "username";
|
|
17
17
|
FieldType["USERNAME_HIDDEN"] = "username-hidden";
|
|
18
|
+
FieldType["CREDIT_CARD"] = "credit-card";
|
|
18
19
|
})(FieldType || (FieldType = {}));
|
|
19
|
-
export
|
|
20
|
-
|
|
20
|
+
export var CCFieldType;
|
|
21
|
+
(function (CCFieldType) {
|
|
22
|
+
CCFieldType["NAME"] = "cc:name";
|
|
23
|
+
CCFieldType["FIRSTNAME"] = "cc:firstname";
|
|
24
|
+
CCFieldType["LASTNAME"] = "cc:lastname";
|
|
25
|
+
CCFieldType["NUMBER"] = "cc:number";
|
|
26
|
+
CCFieldType["CSC"] = "cc:cvc";
|
|
27
|
+
CCFieldType["EXP"] = "cc:exp";
|
|
28
|
+
CCFieldType["EXP_YEAR"] = "cc:exp-year";
|
|
29
|
+
CCFieldType["EXP_MONTH"] = "cc:exp-month";
|
|
30
|
+
})(CCFieldType || (CCFieldType = {}));
|
|
31
|
+
export const ccFields = new Set(Object.values(CCFieldType));
|
|
32
|
+
export var IdentityFieldType;
|
|
33
|
+
(function (IdentityFieldType) {
|
|
34
|
+
IdentityFieldType["FULLNAME"] = "id:fullname";
|
|
35
|
+
IdentityFieldType["FIRSTNAME"] = "id:firstname";
|
|
36
|
+
IdentityFieldType["MIDDLENAME"] = "id:middlname";
|
|
37
|
+
IdentityFieldType["LASTNAME"] = "id:lastname";
|
|
38
|
+
IdentityFieldType["TELEPHONE"] = "id:tel";
|
|
39
|
+
IdentityFieldType["ADDRESS"] = "id:address";
|
|
40
|
+
IdentityFieldType["STATE"] = "id:state";
|
|
41
|
+
IdentityFieldType["CITY"] = "id:city";
|
|
42
|
+
IdentityFieldType["ZIPCODE"] = "id:zipcode";
|
|
43
|
+
IdentityFieldType["ORGANIZATION"] = "id:org";
|
|
44
|
+
IdentityFieldType["COUNTRY"] = "id:country";
|
|
45
|
+
IdentityFieldType["EMAIL"] = "id:email";
|
|
46
|
+
})(IdentityFieldType || (IdentityFieldType = {}));
|
|
47
|
+
export const identityFields = new Set(Object.values(IdentityFieldType));
|
|
48
|
+
export const fieldClasses = ["email", "otp", "password", "new-password", "username", "username-hidden"];
|
|
49
|
+
export const formClasses = ["login", "password-change", "recovery", "register"];
|
|
50
|
+
export const detectionClasses = [...fieldClasses, ...formClasses];
|
|
51
|
+
export const abstractDetectionClasses = ["field", "form"];
|
|
52
|
+
export const modelNames = ["dev_perceptron", "dev_randomForest"];
|
|
53
|
+
export const computeFeatures = (featureComputer, fnode) => featureComputer.compute(fnode);
|
package/utils/attributes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sanitizeStringWithSpaces } from "./text";
|
|
2
|
-
export const TEXT_ATTRIBUTES = ["title", "
|
|
2
|
+
export const TEXT_ATTRIBUTES = ["title", "aria-label", "aria-labelledby", "aria-describedby", "placeholder", "legend", "label"];
|
|
3
3
|
export const EL_ATTRIBUTES = ["id", "class", "role", "jsaction", "ng-controller", "data-bind", "ng-model", "v-model", "v-bind", "data-testid", "href"];
|
|
4
4
|
export const FORM_ATTRIBUTES = [EL_ATTRIBUTES, "name", "action"].flat();
|
|
5
5
|
export const FIELD_ATTRIBUTES = [EL_ATTRIBUTES, "name", "inputmode"].flat();
|
package/utils/clustering.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { clusters as clustering } from "@protontech/fathom";
|
|
2
|
-
import {
|
|
2
|
+
import { inputCandidateSelector, kButtonSelector, kButtonSubmitSelector, kDomClusterSelector, kFieldSelector } from "../constants/selectors";
|
|
3
3
|
import { findStackedParents, getCommonAncestor, getRectMinDistance, pruneNested, uniqueNodes, walkUpWhile } from "./dom";
|
|
4
4
|
import { isBtnCandidate } from "./field";
|
|
5
5
|
import { isVisibleField } from "./visible";
|
|
6
|
+
import { isTopFrame } from "./exclusion";
|
|
6
7
|
import { flagCluster, isClassifiable } from "./flags";
|
|
7
8
|
import { selectFormCandidates } from "./form";
|
|
9
|
+
import { isIFrameField } from "./iframe";
|
|
8
10
|
const { clusters } = clustering;
|
|
9
11
|
const CLUSTER_MAX_X_DIST = 50;
|
|
10
12
|
const CLUSTER_MAX_Y_DIST = 275;
|
|
@@ -42,7 +44,13 @@ const compare = (elA, elB) => {
|
|
|
42
44
|
};
|
|
43
45
|
const handleSingletonCluster = (cluster) => {
|
|
44
46
|
const node = cluster[0];
|
|
45
|
-
return walkUpWhile(node, 5)((
|
|
47
|
+
return walkUpWhile(node, 5)((parent, candidate) => {
|
|
48
|
+
if (parent.tagName === "HTML")
|
|
49
|
+
return false;
|
|
50
|
+
if (candidate === node)
|
|
51
|
+
return true;
|
|
52
|
+
return candidate.querySelectorAll(kButtonSelector).length === 0;
|
|
53
|
+
});
|
|
46
54
|
};
|
|
47
55
|
export const resolveFormClusters = (doc) => {
|
|
48
56
|
const forms = selectFormCandidates(doc);
|
|
@@ -52,11 +60,12 @@ export const resolveFormClusters = (doc) => {
|
|
|
52
60
|
const inputs = fieldsOfInterest.filter((field) => field.matches(inputCandidateSelector));
|
|
53
61
|
if (inputs.length === 0 || inputs.length > CLUSTER_MAX_ELEMENTS)
|
|
54
62
|
return [];
|
|
55
|
-
const domGroups = Array.from(doc.querySelectorAll(
|
|
63
|
+
const domGroups = Array.from(doc.querySelectorAll(kDomClusterSelector)).filter((el) => el !== document.body);
|
|
56
64
|
const positionedEls = findStackedParents(inputs, 20);
|
|
57
65
|
const groups = pruneNested(domGroups.filter((el) => !positionedEls.some((stack) => el.contains(stack))).concat(positionedEls));
|
|
58
66
|
const buttons = clusterable(Array.from(document.querySelectorAll(kButtonSubmitSelector)).filter(isBtnCandidate));
|
|
59
|
-
const
|
|
67
|
+
const iframes = clusterable(Array.from(doc.querySelectorAll("iframe")).filter(isIFrameField));
|
|
68
|
+
const candidates = uniqueNodes(fieldsOfInterest, buttons, iframes);
|
|
60
69
|
if (candidates.length > CLUSTER_MAX_ELEMENTS)
|
|
61
70
|
return [];
|
|
62
71
|
const groupByInput = new WeakMap(candidates.map((el) => [el, groups.find((group) => group.contains(el))]));
|
|
@@ -73,7 +82,11 @@ export const resolveFormClusters = (doc) => {
|
|
|
73
82
|
});
|
|
74
83
|
const ancestors = theClusters
|
|
75
84
|
.map((cluster) => (cluster.length === 1 ? handleSingletonCluster(cluster) : cluster.reduce(getCommonAncestor)))
|
|
76
|
-
.filter((ancestor) =>
|
|
85
|
+
.filter((ancestor) => {
|
|
86
|
+
if (isTopFrame() && document.body === ancestor)
|
|
87
|
+
return false;
|
|
88
|
+
return ancestor.querySelectorAll(inputCandidateSelector).length > 0;
|
|
89
|
+
});
|
|
77
90
|
const result = pruneNested(ancestors);
|
|
78
91
|
result.forEach(flagCluster);
|
|
79
92
|
context.cache = new WeakMap();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CCFieldType } from "@protontech/autofill/types";
|
|
2
|
+
import type { Fnode } from "@protontech/fathom";
|
|
3
|
+
export type CCFieldElement = HTMLInputElement | HTMLSelectElement;
|
|
4
|
+
export type CCExpirationMonthFormat = {
|
|
5
|
+
padding: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type CCExpirationYearFormat = {
|
|
8
|
+
fullYear: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type CCExpirationFormat = {
|
|
11
|
+
separator: string;
|
|
12
|
+
fullYear: boolean;
|
|
13
|
+
monthFirst: boolean;
|
|
14
|
+
};
|
|
15
|
+
type CCFieldMatchParams = {
|
|
16
|
+
visible: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare const CC_ATTRIBUTES: string[];
|
|
19
|
+
export declare const CC_INPUT_TYPES: string[];
|
|
20
|
+
export declare const getExpirationFormat: (field: HTMLElement, allowFallback?: boolean) => CCExpirationFormat | undefined;
|
|
21
|
+
export declare const formatExpirationDate: (month: string, year: string, { fullYear, separator, monthFirst }: CCExpirationFormat) => string;
|
|
22
|
+
export declare const getInputExpirationMonthFormat: (input: HTMLInputElement) => CCExpirationMonthFormat;
|
|
23
|
+
export declare const getInputExpirationYearFormat: (input: HTMLInputElement) => CCExpirationYearFormat;
|
|
24
|
+
export declare const getSelectExpirationYearFormat: (select: HTMLSelectElement) => CCExpirationYearFormat | undefined;
|
|
25
|
+
export declare const getSelectExpirationMonthFormat: (select: HTMLSelectElement) => CCExpirationMonthFormat | undefined;
|
|
26
|
+
export declare const getCCHaystack: (field: HTMLElement) => string;
|
|
27
|
+
export declare const getCachedCCSubtype: (el: HTMLElement) => CCFieldType | undefined;
|
|
28
|
+
export declare const getCCFieldType: (field: CCFieldElement) => CCFieldType | undefined;
|
|
29
|
+
export declare const matchCCFieldCandidate: (input: HTMLInputElement, { visible }: CCFieldMatchParams) => boolean;
|
|
30
|
+
export declare const isCCInputField: (fnode: Fnode) => boolean;
|
|
31
|
+
export declare const isCCSelectField: (fnode: Fnode) => boolean;
|
|
32
|
+
export {};
|