265 lines
7.5 KiB
JavaScript
265 lines
7.5 KiB
JavaScript
/* 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.
|
|
*/
|
|
|
|
import {
|
|
FormAutofillStorageBase,
|
|
CreditCardsBase,
|
|
AddressesBase,
|
|
} from "resource://autofill/FormAutofillStorageBase.sys.mjs";
|
|
import { JSONFile } from "resource://gre/modules/JSONFile.sys.mjs";
|
|
|
|
const lazy = {};
|
|
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
Address: "resource://gre/modules/GeckoViewAutocomplete.sys.mjs",
|
|
CreditCard: "resource://gre/modules/GeckoViewAutocomplete.sys.mjs",
|
|
GeckoViewAutocomplete: "resource://gre/modules/GeckoViewAutocomplete.sys.mjs",
|
|
});
|
|
|
|
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) {
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) {
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* Find a duplicate credit card record in the storage.
|
|
*
|
|
* A record is considered as a duplicate of another record when two records
|
|
* are the "same". This might be true even when some of their fields are
|
|
* different. For example, one record has the same credit card number but has
|
|
* different expiration date as the other record are still considered as
|
|
* "duplicate".
|
|
* This is different from `getMatchRecord`, which ensures all the fields with
|
|
* value in the the record is equal to the returned record.
|
|
*
|
|
* @param {object} record
|
|
* The credit card for duplication checking. please make sure the
|
|
* record is normalized.
|
|
* @returns {object}
|
|
* Return the first duplicated record found in storage, null otherwise.
|
|
*/
|
|
async *getDuplicateRecords(record) {
|
|
if (!record["cc-number"]) {
|
|
return null;
|
|
}
|
|
|
|
await this._store.updateCreditCards();
|
|
for (const recordInStorage of this._data) {
|
|
if (recordInStorage.deleted) {
|
|
continue;
|
|
}
|
|
|
|
if (recordInStorage["cc-number"] == record["cc-number"]) {
|
|
yield recordInStorage;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async reconcile(_remoteRecord) {
|
|
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
|
}
|
|
|
|
async findDuplicateGUID(_remoteRecord) {
|
|
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
|
|
}
|
|
}
|
|
|
|
export 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.
|
|
export const formAutofillStorage = new FormAutofillStorage();
|