Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / base / IndexedDBHelper.jsm
bloba3024c009a396b94f35a66c0842c8f8d69f06b42
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 file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 let DEBUG = 0;
8 let debug;
9 if (DEBUG) {
10   debug = function (s) { dump("-*- IndexedDBHelper: " + s + "\n"); }
11 } else {
12   debug = function (s) {}
15 const Cu = Components.utils;
16 const Cc = Components.classes;
17 const Ci = Components.interfaces;
19 this.EXPORTED_SYMBOLS = ["IndexedDBHelper"];
21 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
22 Cu.importGlobalProperties(["indexedDB"]);
24 XPCOMUtils.defineLazyModuleGetter(this, 'Services',
25   'resource://gre/modules/Services.jsm');
27 this.IndexedDBHelper = function IndexedDBHelper() {}
29 IndexedDBHelper.prototype = {
31   // Cache the database
32   _db: null,
34   // Close the database
35   close: function close() {
36     if (this._db) {
37       this._db.close();
38       this._db = null;
39     }
40   },
42   /**
43    * Open a new database.
44    * User has to provide upgradeSchema.
45    *
46    * @param successCb
47    *        Success callback to call once database is open.
48    * @param failureCb
49    *        Error callback to call when an error is encountered.
50    */
51   open: function open(aSuccessCb, aFailureCb) {
52     let self = this;
53     if (DEBUG) debug("Try to open database:" + self.dbName + " " + self.dbVersion);
54     let req = indexedDB.open(this.dbName, this.dbVersion);
55     req.onsuccess = function (event) {
56       if (DEBUG) debug("Opened database:" + self.dbName + " " + self.dbVersion);
57       self._db = event.target.result;
58       self._db.onversionchange = function(event) {
59         if (DEBUG) debug("WARNING: DB modified from a different window.");
60       }
61       aSuccessCb && aSuccessCb();
62     };
64     req.onupgradeneeded = function (aEvent) {
65       if (DEBUG) {
66         debug("Database needs upgrade:" + self.dbName + aEvent.oldVersion + aEvent.newVersion);
67         debug("Correct new database version:" + (aEvent.newVersion == this.dbVersion));
68       }
70       let _db = aEvent.target.result;
71       self.upgradeSchema(req.transaction, _db, aEvent.oldVersion, aEvent.newVersion);
72     };
73     req.onerror = function (aEvent) {
74       if (DEBUG) debug("Failed to open database: " + self.dbName);
75       aFailureCb && aFailureCb(aEvent.target.error.name);
76     };
77     req.onblocked = function (aEvent) {
78       if (DEBUG) debug("Opening database request is blocked.");
79     };
80   },
82   /**
83    * Use the cached DB or open a new one.
84    *
85    * @param successCb
86    *        Success callback to call.
87    * @param failureCb
88    *        Error callback to call when an error is encountered.
89    */
90   ensureDB: function ensureDB(aSuccessCb, aFailureCb) {
91     if (this._db) {
92       if (DEBUG) debug("ensureDB: already have a database, returning early.");
93       if (aSuccessCb) {
94         Services.tm.currentThread.dispatch(aSuccessCb,
95                                            Ci.nsIThread.DISPATCH_NORMAL);
96       }
97       return;
98     }
99     this.open(aSuccessCb, aFailureCb);
100   },
102   /**
103    * Start a new transaction.
104    *
105    * @param txn_type
106    *        Type of transaction (e.g. "readwrite")
107    * @param store_name
108    *        The object store you want to be passed to the callback
109    * @param callback
110    *        Function to call when the transaction is available. It will
111    *        be invoked with the transaction and the `store' object store.
112    * @param successCb
113    *        Success callback to call on a successful transaction commit.
114    *        The result is stored in txn.result.
115    * @param failureCb
116    *        Error callback to call when an error is encountered.
117    */
118   newTxn: function newTxn(txn_type, store_name, callback, successCb, failureCb) {
119     this.ensureDB(function () {
120       if (DEBUG) debug("Starting new transaction" + txn_type);
121       let txn = this._db.transaction(Array.isArray(store_name) ? store_name : this.dbStoreNames, txn_type);
122       if (DEBUG) debug("Retrieving object store", this.dbName);
123       let stores;
124       if (Array.isArray(store_name)) {
125         stores = [];
126         for (let i = 0; i < store_name.length; ++i) {
127           stores.push(txn.objectStore(store_name[i]));
128         }
129       } else {
130         stores = txn.objectStore(store_name);
131       }
133       txn.oncomplete = function (event) {
134         if (DEBUG) debug("Transaction complete. Returning to callback.");
135         if (successCb) {
136           successCb(txn.result);
137         }
138       };
140       txn.onabort = function (event) {
141         if (DEBUG) debug("Caught error on transaction");
142         /*
143          * event.target.error may be null
144          * if txn was aborted by calling txn.abort()
145          */
146         if (failureCb) {
147           if (event.target.error) {
148             failureCb(event.target.error.name);
149           } else {
150             failureCb("UnknownError");
151           }
152         }
153       };
154       callback(txn, stores);
155     }.bind(this), failureCb);
156   },
158   /**
159    * Initialize the DB. Does not call open.
160    *
161    * @param aDBName
162    *        DB name for the open call.
163    * @param aDBVersion
164    *        Current DB version. User has to implement upgradeSchema.
165    * @param aDBStoreName
166    *        ObjectStore that is used.
167    */
168   initDBHelper: function initDBHelper(aDBName, aDBVersion, aDBStoreNames) {
169     this.dbName = aDBName;
170     this.dbVersion = aDBVersion;
171     this.dbStoreNames = aDBStoreNames;
172   }