n a new one. * * @param successCb * Success callback to call. * @param failureCb * Error callback to call when an error is encountered. */ ensureDB: function ensureDB(aSuccessCb, aFailureCb) { if (this._db) { if (DEBUG) { debug("ensureDB: already have a database, returning early."); } if (aSuccessCb) { Services.tm.dispatchToMainThread(aSuccessCb); } return; } this.open(aError => { if (aError) { aFailureCb && aFailureCb(aError); } else { aSuccessCb && aSuccessCb(); } }); }, /** * Start a new transaction. * * @param txn_type * Type of transaction (e.g. "readwrite") * @param store_name * The object store you want to be passed to the callback * @param callback * Function to call when the transaction is available. It will * be invoked with the transaction and the `store' object store. * @param successCb * Success callback to call on a successful transaction commit. * The result is stored in txn.result (in the callback function). * @param failureCb * Error callback to call when an error is encountered. */ newTxn: function newTxn( txn_type, store_name, callback, successCb, failureCb ) { this.ensureDB(() => { if (DEBUG) { debug("Starting new transaction" + txn_type); } let txn; try { txn = this._db.transaction( Array.isArray(store_name) ? store_name : this.dbStoreNames, txn_type ); } catch (e) { if (DEBUG) { debug("Error starting transaction: " + this.dbName); } failureCb(getErrorName(e)); return; } if (DEBUG) { debug("Retrieving object store: " + this.dbName); } let stores; if (Array.isArray(store_name)) { stores = []; for (let i = 0; i < store_name.length; ++i) { stores.push(txn.objectStore(store_name[i])); } } else { stores = txn.objectStore(store_name); } txn.oncomplete = function () { if (DEBUG) { debug("Transaction complete. Returning to callback."); } /* * txn.result property is not part of the transaction object returned * by this._db.transaction method called above. * The property is expected to be set in the callback function. * However, it can happen that the property is not set for some reason, * so we have to check if the property exists before calling the * success callback. */ if (successCb) { if ("result" in txn) { successCb(txn.result); } else { successCb(); } } }; txn.onabort = function () { if (DEBUG) { debug("Caught error on transaction"); } /* * txn.error property is part of the transaction object returned by * this._db.transaction method called above. * The attribute is defined in IDBTranscation WebIDL interface. * It may be null. */ if (failureCb) { failureCb(getErrorName(txn.error)); } }; callback(txn, stores); }, failureCb); }, /** * Initialize the DB. Does not call open. * * @param aDBName * DB name for the open call. * @param aDBVersion * Current DB version. User has to implement upgradeSchema. * @param aDBStoreName * ObjectStore that is used. */ initDBHelper: function initDBHelper(aDBName, aDBVersion, aDBStoreNames) { this.dbName = aDBName; this.dbVersion = aDBVersion; this.dbStoreNames = aDBStoreNames; // Cache the database. this._db = null; this._waitForOpenCallbacks = new Set(); }, }; PK