summaryrefslogtreecommitdiffstats
path: root/toolkit/components/formautofill/android/FormAutofillStorage.jsm
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /toolkit/components/formautofill/android/FormAutofillStorage.jsm
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/formautofill/android/FormAutofillStorage.jsm')
-rw-r--r--toolkit/components/formautofill/android/FormAutofillStorage.jsm277
1 files changed, 277 insertions, 0 deletions
diff --git a/toolkit/components/formautofill/android/FormAutofillStorage.jsm b/toolkit/components/formautofill/android/FormAutofillStorage.jsm
new file mode 100644
index 0000000000..794b8ecdbd
--- /dev/null
+++ b/toolkit/components/formautofill/android/FormAutofillStorage.jsm
@@ -0,0 +1,277 @@
+/* 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/. */
+
+/*
+ * Implements an interface of the storage of Form Autofill for GeckoView.
+ */
+
+"use strict";
+
+// We expose a singleton from this module. Some tests may import the
+// constructor via a backstage pass.
+const EXPORTED_SYMBOLS = ["formAutofillStorage", "FormAutofillStorage"];
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+const {
+ FormAutofillStorageBase,
+ CreditCardsBase,
+ AddressesBase,
+} = ChromeUtils.import("resource://autofill/FormAutofillStorageBase.jsm");
+const { JSONFile } = ChromeUtils.importESModule(
+ "resource://gre/modules/JSONFile.sys.mjs"
+);
+
+const lazy = {};
+
+XPCOMUtils.defineLazyModuleGetters(lazy, {
+ Address: "resource://gre/modules/GeckoViewAutocomplete.jsm",
+ CreditCard: "resource://gre/modules/GeckoViewAutocomplete.jsm",
+ GeckoViewAutocomplete: "resource://gre/modules/GeckoViewAutocomplete.jsm",
+});
+
+class GeckoViewStorage extends JSONFile {
+ constructor() {
+ super({ path: null, sanitizedBasename: "GeckoViewStorage" });
+ }
+
+ async updateCreditCards() {
+ const creditCards = await lazy.GeckoViewAutocomplete.fetchCreditCards().then(
+ results => results?.map(r => lazy.CreditCard.parse(r).toGecko()) ?? [],
+ _ => []
+ );
+ super.data.creditCards = creditCards;
+ }
+
+ async updateAddresses() {
+ const addresses = await lazy.GeckoViewAutocomplete.fetchAddresses().then(
+ results => results?.map(r => lazy.Address.parse(r).toGecko()) ?? [],
+ _ => []
+ );
+ super.data.addresses = addresses;
+ }
+
+ async load() {
+ super.data = { creditCards: {}, addresses: {} };
+ await this.updateCreditCards();
+ await this.updateAddresses();
+ }
+
+ ensureDataReady() {
+ if (this.dataReady) {
+ return;
+ }
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+
+ async _save() {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+}
+
+class Addresses extends AddressesBase {
+ // Override AutofillRecords methods.
+
+ _initialize() {
+ this._initializePromise = Promise.resolve();
+ }
+
+ async _saveRecord(record, { sourceSync = false } = {}) {
+ lazy.GeckoViewAutocomplete.onAddressSave(lazy.Address.fromGecko(record));
+ }
+
+ /**
+ * Returns the record with the specified GUID.
+ *
+ * @param {string} guid
+ * Indicates which record to retrieve.
+ * @param {object} options
+ * @param {boolean} [options.rawData = false]
+ * Returns a raw record without modifications and the computed fields
+ * (this includes private fields)
+ * @returns {Promise<object>}
+ * A clone of the record.
+ */
+ async get(guid, { rawData = false } = {}) {
+ await this._store.updateAddresses();
+ return super.get(guid, { rawData });
+ }
+
+ /**
+ * Returns all records.
+ *
+ * @param {object} options
+ * @param {boolean} [options.rawData = false]
+ * Returns raw records without modifications and the computed fields.
+ * @param {boolean} [options.includeDeleted = false]
+ * Also return any tombstone records.
+ * @returns {Promise<Array.<object>>}
+ * An array containing clones of all records.
+ */
+ async getAll({ rawData = false, includeDeleted = false } = {}) {
+ await this._store.updateAddresses();
+ return super.getAll({ rawData, includeDeleted });
+ }
+
+ /**
+ * Return all saved field names in the collection.
+ *
+ * @returns {Set} Set containing saved field names.
+ */
+ async getSavedFieldNames() {
+ await this._store.updateAddresses();
+ return super.getSavedFieldNames();
+ }
+
+ async reconcile(remoteRecord) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+
+ async findDuplicateGUID(remoteRecord) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+
+ async mergeToStorage(targetRecord, strict = false) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+}
+
+class CreditCards extends CreditCardsBase {
+ async _encryptNumber(creditCard) {
+ // Don't encrypt or obfuscate for GV, since we don't store or show
+ // the number. The API has to always provide the original number.
+ }
+
+ // Override AutofillRecords methods.
+
+ _initialize() {
+ this._initializePromise = Promise.resolve();
+ }
+
+ async _saveRecord(record, { sourceSync = false } = {}) {
+ lazy.GeckoViewAutocomplete.onCreditCardSave(
+ lazy.CreditCard.fromGecko(record)
+ );
+ }
+
+ /**
+ * Returns the record with the specified GUID.
+ *
+ * @param {string} guid
+ * Indicates which record to retrieve.
+ * @param {object} options
+ * @param {boolean} [options.rawData = false]
+ * Returns a raw record without modifications and the computed fields
+ * (this includes private fields)
+ * @returns {Promise<object>}
+ * A clone of the record.
+ */
+ async get(guid, { rawData = false } = {}) {
+ await this._store.updateCreditCards();
+ return super.get(guid, { rawData });
+ }
+
+ /**
+ * Returns all records.
+ *
+ * @param {object} options
+ * @param {boolean} [options.rawData = false]
+ * Returns raw records without modifications and the computed fields.
+ * @param {boolean} [options.includeDeleted = false]
+ * Also return any tombstone records.
+ * @returns {Promise<Array.<object>>}
+ * An array containing clones of all records.
+ */
+ async getAll({ rawData = false, includeDeleted = false } = {}) {
+ await this._store.updateCreditCards();
+ return super.getAll({ rawData, includeDeleted });
+ }
+
+ /**
+ * Return all saved field names in the collection.
+ *
+ * @returns {Set} Set containing saved field names.
+ */
+ async getSavedFieldNames() {
+ await this._store.updateCreditCards();
+ return super.getSavedFieldNames();
+ }
+
+ /**
+ * Normalize the given record and return the first matched guid if storage has the same record.
+ *
+ * @param {object} targetCreditCard
+ * The credit card for duplication checking.
+ * @returns {Promise<string|null>}
+ * Return the first guid if storage has the same credit card and null otherwise.
+ */
+ async getDuplicateGuid(targetCreditCard) {
+ let clonedTargetCreditCard = this._clone(targetCreditCard);
+ this._normalizeRecord(clonedTargetCreditCard);
+ if (!clonedTargetCreditCard["cc-number"]) {
+ return null;
+ }
+
+ await this._store.updateCreditCards();
+ for (let creditCard of this._data) {
+ if (creditCard.deleted) {
+ continue;
+ }
+
+ if (creditCard["cc-number"] == clonedTargetCreditCard["cc-number"]) {
+ return creditCard.guid;
+ }
+ }
+ return null;
+ }
+
+ async reconcile(remoteRecord) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+
+ async findDuplicateGUID(remoteRecord) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+
+ async mergeToStorage(targetRecord, strict = false) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ }
+}
+
+class FormAutofillStorage extends FormAutofillStorageBase {
+ constructor() {
+ super(null);
+ }
+
+ getAddresses() {
+ if (!this._addresses) {
+ this._store.ensureDataReady();
+ this._addresses = new Addresses(this._store);
+ }
+ return this._addresses;
+ }
+
+ getCreditCards() {
+ if (!this._creditCards) {
+ this._store.ensureDataReady();
+ this._creditCards = new CreditCards(this._store);
+ }
+ return this._creditCards;
+ }
+
+ /**
+ * Initializes the in-memory async store API.
+ *
+ * @returns {JSONFile}
+ * The JSONFile store.
+ */
+ _initializeStore() {
+ return new GeckoViewStorage();
+ }
+}
+
+// The singleton exposed by this module.
+const formAutofillStorage = new FormAutofillStorage();