/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { createEngine, FEATURES, } from "chrome://global/content/ml/EngineProcess.sys.mjs"; import { AIFeature } from "chrome://global/content/ml/AIFeature.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { AutofillTelemetry: "resource://gre/modules/shared/AutofillTelemetry.sys.mjs", FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs", }); const FORM_AUTOFILL_FEATURE_ID = "formfill-classification"; const ML_TASKNAME = "text-classification"; const FormFill_Config = { timeoutMS: 2 * 60 * 1000, // 2 minutes taskName: ML_TASKNAME, featureId: FORM_AUTOFILL_FEATURE_ID, engineId: FEATURES[FORM_AUTOFILL_FEATURE_ID].engineId, backend: "onnx-native", fallbackBackend: "onnx", modelId: "mozilla/tinybert-address-autofill", modelRevision: "v0.1.0", // The dtype will need to be updated as needed. dtype: "fp32", }; export class FormAutofillML extends AIFeature { static async id() { return "formfill-ml"; } // For now, these are just placeholders. static async enable() {} static async block() {} static async makeAvailable() {} static async isEnabled() { return true; } static async isAllowed() { return true; } static async isBlocked() { return false; } static async isManagedByPolicy() { return false; } static addToHash(hash, str) { for (let i of str) { hash = ((hash << 5) - hash + i.charCodeAt(0)) | 0; } return hash; } static async detectFields(window, fieldDetails) { let engine; try { engine = await createEngine(FormFill_Config); } catch (ex) { return; } // Hash of the data for the form let hash = 0; let beforeTime = window.performance.now(); let results = []; for (let fd of fieldDetails) { const request = { args: [fd.extraInfo.mlData], options: { pooling: "mean", normalize: true }, }; hash = this.addToHash(hash, fd.extraInfo.mlData); let result = await engine.run(request); results.push(result[0].label == "other" ? "" : result[0].label); } let mlTime = window.performance.now() - beforeTime; let mlEnabled = lazy.FormAutofillUtils.enableMLAutofill; // If ML is enabled, then it will be used for autofill. // Otherwise, we just calculate the ML inferred fields for // telemetry but don't use them for autofill. for (let f = 0; f < fieldDetails.length; f++) { fieldDetails[f].mlFieldName = results[f]; if (mlEnabled) { fieldDetails[f].fieldName = results[f]; } } lazy.AutofillTelemetry.recordMLDetection(fieldDetails, hash, mlTime); } }