1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5/* This is a JavaScript module (JSM) to be imported via 6 * Components.utils.import() and acts as a singleton. Only the following 7 * listed symbols will exposed on import, and only when and where imported. 8 */ 9 10var EXPORTED_SYMBOLS = [ 11 "Address", 12 "CreditCard", 13 "DumpAddresses", 14 "DumpCreditCards", 15]; 16 17const { Logger } = ChromeUtils.import("resource://tps/logger.jsm"); 18 19ChromeUtils.defineModuleGetter( 20 this, 21 "formAutofillStorage", 22 "resource://formautofill/FormAutofillStorage.jsm" 23); 24 25ChromeUtils.defineModuleGetter( 26 this, 27 "OSKeyStore", 28 "resource://gre/modules/OSKeyStore.jsm" 29); 30 31class FormAutofillBase { 32 constructor(props, subStorageName, fields) { 33 this._subStorageName = subStorageName; 34 this._fields = fields; 35 36 this.props = {}; 37 this.updateProps = null; 38 if ("changes" in props) { 39 this.updateProps = props.changes; 40 } 41 for (const field of this._fields) { 42 this.props[field] = field in props ? props[field] : null; 43 } 44 } 45 46 async getStorage() { 47 await formAutofillStorage.initialize(); 48 return formAutofillStorage[this._subStorageName]; 49 } 50 51 async Create() { 52 const storage = await this.getStorage(); 53 await storage.add(this.props); 54 } 55 56 async Find() { 57 const storage = await this.getStorage(); 58 return storage._data.find(entry => 59 this._fields.every(field => entry[field] === this.props[field]) 60 ); 61 } 62 63 async Update() { 64 const storage = await this.getStorage(); 65 const { guid } = await this.Find(); 66 await storage.update(guid, this.updateProps, true); 67 } 68 69 async Remove() { 70 const storage = await this.getStorage(); 71 const { guid } = await this.Find(); 72 storage.remove(guid); 73 } 74} 75 76async function DumpStorage(subStorageName) { 77 await formAutofillStorage.initialize(); 78 Logger.logInfo(`\ndumping ${subStorageName} list\n`, true); 79 const entries = formAutofillStorage[subStorageName]._data; 80 for (const entry of entries) { 81 Logger.logInfo(JSON.stringify(entry), true); 82 } 83 Logger.logInfo(`\n\nend ${subStorageName} list\n`, true); 84} 85 86const ADDRESS_FIELDS = [ 87 "given-name", 88 "additional-name", 89 "family-name", 90 "organization", 91 "street-address", 92 "address-level2", 93 "address-level1", 94 "postal-code", 95 "country", 96 "tel", 97 "email", 98]; 99 100class Address extends FormAutofillBase { 101 constructor(props) { 102 super(props, "addresses", ADDRESS_FIELDS); 103 } 104} 105 106async function DumpAddresses() { 107 await DumpStorage("addresses"); 108} 109 110const CREDIT_CARD_FIELDS = [ 111 "cc-name", 112 "cc-number", 113 "cc-exp-month", 114 "cc-exp-year", 115]; 116 117class CreditCard extends FormAutofillBase { 118 constructor(props) { 119 super(props, "creditCards", CREDIT_CARD_FIELDS); 120 } 121 122 async Find() { 123 const storage = await this.getStorage(); 124 await Promise.all( 125 storage._data.map( 126 async entry => 127 (entry["cc-number"] = await OSKeyStore.decrypt( 128 entry["cc-number-encrypted"] 129 )) 130 ) 131 ); 132 return storage._data.find(entry => { 133 return this._fields.every(field => entry[field] === this.props[field]); 134 }); 135 } 136} 137 138async function DumpCreditCards() { 139 await DumpStorage("creditCards"); 140} 141