mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 746933 - Create a JS helper module for common IndexedDB functionality. r=fabrice
This commit is contained in:
parent
d971875173
commit
f3aea8b4a6
154
dom/base/IndexedDBHelper.jsm
Normal file
154
dom/base/IndexedDBHelper.jsm
Normal file
@ -0,0 +1,154 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
let DEBUG = 0;
|
||||
if (DEBUG) {
|
||||
debug = function (s) { dump("-*- IndexedDBHelper: " + s + "\n"); }
|
||||
} else {
|
||||
debug = function (s) {}
|
||||
}
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["IndexedDBHelper"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function IndexedDBHelper() { }
|
||||
|
||||
IndexedDBHelper.prototype = {
|
||||
|
||||
// Cache the database
|
||||
_db: null,
|
||||
|
||||
// Close the database
|
||||
close: function close() {
|
||||
if (this._db) {
|
||||
this._db.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open a new database.
|
||||
* User has to provide createSchema and upgradeSchema.
|
||||
*
|
||||
* @param successCb
|
||||
* Success callback to call once database is open.
|
||||
* @param failureCb
|
||||
* Error callback to call when an error is encountered.
|
||||
*/
|
||||
open: function open(aSuccessCb, aFailureCb) {
|
||||
let self = this;
|
||||
debug("Try to open database:" + this.dbName + " " + this.dbVersion);
|
||||
let req = this.dbGlobal.mozIndexedDB.open(this.dbName, this.dbVersion);
|
||||
req.onsuccess = function (event) {
|
||||
debug("Opened database:" + self.dbName + " " + self.dbName);
|
||||
self._db = event.target.result;
|
||||
self._db.onversionchange = function(event) {
|
||||
debug("WARNING: DB modified from a different window.");
|
||||
}
|
||||
aSuccessCb();
|
||||
};
|
||||
|
||||
req.onupgradeneeded = function (aEvent) {
|
||||
debug("Database needs upgrade:" + this.dbName + aEvent.oldVersion + aEvent.newVersion);
|
||||
debug("Correct new database version:" + aEvent.newVersion == this.dbVersion);
|
||||
|
||||
let _db = aEvent.target.result;
|
||||
switch (aEvent.oldVersion) {
|
||||
case 0:
|
||||
debug("New database");
|
||||
self.createSchema(_db);
|
||||
break;
|
||||
default:
|
||||
self.upgradeSchema(_db, aEvent.oldVersion, aEvent.newVersion);
|
||||
break;
|
||||
}
|
||||
};
|
||||
req.onerror = function (aEvent) {
|
||||
debug("Failed to open database:" + this.dbName);
|
||||
aFailureCb(aEvent.target.errorMessage);
|
||||
};
|
||||
req.onblocked = function (aEvent) {
|
||||
debug("Opening database request is blocked.");
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Use the cached DB or open 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) {
|
||||
debug("ensureDB: already have a database, returning early.");
|
||||
aSuccessCb();
|
||||
return;
|
||||
}
|
||||
this.open(aSuccessCb, aFailureCb);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new transaction.
|
||||
*
|
||||
* @param txn_type
|
||||
* Type of transaction (e.g. "readwrite")
|
||||
* @param callback
|
||||
* Function to call when the transaction is available. It will
|
||||
* be invoked with the transaction and the 'aDBStoreName' object store.
|
||||
* @param successCb
|
||||
* Success callback to call on a successful transaction commit.
|
||||
* The result is stored in txn.result.
|
||||
* @param failureCb
|
||||
* Error callback to call when an error is encountered.
|
||||
*/
|
||||
newTxn: function newTxn(txn_type, callback, successCb, failureCb) {
|
||||
this.ensureDB(function () {
|
||||
debug("Starting new transaction" + txn_type);
|
||||
let txn = this._db.transaction(this.dbName, txn_type);
|
||||
debug("Retrieving object store", this.dbName);
|
||||
let store = txn.objectStore(this.dbStoreName);
|
||||
|
||||
txn.oncomplete = function (event) {
|
||||
debug("Transaction complete. Returning to callback.");
|
||||
successCb(txn.result);
|
||||
};
|
||||
|
||||
txn.onabort = function (event) {
|
||||
debug("Caught error on transaction");
|
||||
// FIXXMEE: this will work in the future. Bug 748630
|
||||
// failureCb(event.target.error.name);
|
||||
failureCb("UnknownError");
|
||||
};
|
||||
callback(txn, store);
|
||||
}.bind(this), 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 createSchema and upgradeSchema.
|
||||
* @param aDBStoreName
|
||||
* ObjectStore that is used.
|
||||
* @param aGlobal
|
||||
* Global object that has mozIndexedDB property.
|
||||
*/
|
||||
initDBHelper: function initDBHelper(aDBName, aDBVersion, aDBStoreName, aGlobal) {
|
||||
this.dbName = aDBName;
|
||||
this.dbVersion = aDBVersion;
|
||||
this.dbStoreName = aDBStoreName;
|
||||
this.dbGlobal = aGlobal;
|
||||
}
|
||||
}
|
@ -52,25 +52,27 @@ DIRS = \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
ConsoleAPI.js \
|
||||
ConsoleAPI.manifest \
|
||||
BrowserElementAPI.js \
|
||||
BrowserElementAPI.manifest \
|
||||
$(NULL)
|
||||
ConsoleAPI.js \
|
||||
ConsoleAPI.manifest \
|
||||
BrowserElementAPI.js \
|
||||
BrowserElementAPI.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
|
||||
$(NULL)
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
Webapps.js \
|
||||
Webapps.manifest \
|
||||
$(NULL)
|
||||
Webapps.js \
|
||||
Webapps.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES += Webapps.jsm \
|
||||
$(NULL)
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES += DOMRequestHelper.jsm \
|
||||
$(NULL)
|
||||
EXTRA_JS_MODULES += \
|
||||
DOMRequestHelper.jsm \
|
||||
IndexedDBHelper.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMDOMError.idl \
|
||||
|
@ -8,16 +8,18 @@ const EXPORTED_SYMBOLS = ['ContactDB'];
|
||||
|
||||
let DEBUG = 0;
|
||||
/* static functions */
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- ContactDB component: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
if (DEBUG) {
|
||||
debug = function (s) { dump("-*- ContactDB component: " + s + "\n"); }
|
||||
} else {
|
||||
debug = function (s) {}
|
||||
}
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
const DB_NAME = "contacts";
|
||||
const DB_VERSION = 1;
|
||||
@ -29,66 +31,7 @@ function ContactDB(aGlobal) {
|
||||
}
|
||||
|
||||
ContactDB.prototype = {
|
||||
|
||||
// Cache the DB
|
||||
db: null,
|
||||
|
||||
close: function close() {
|
||||
debug("close");
|
||||
if (this.db)
|
||||
this.db.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare the database. This may include opening the database and upgrading
|
||||
* it to the latest schema version.
|
||||
*
|
||||
* @return (via callback) a database ready for use.
|
||||
*/
|
||||
ensureDB: function ensureDB(callback, failureCb) {
|
||||
if (this.db) {
|
||||
debug("ensureDB: already have a database, returning early.");
|
||||
callback(this.db);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
debug("try to open database:" + DB_NAME + " " + DB_VERSION);
|
||||
let request = this._global.mozIndexedDB.open(DB_NAME, DB_VERSION);
|
||||
request.onsuccess = function (event) {
|
||||
debug("Opened database:", DB_NAME, DB_VERSION);
|
||||
self.db = event.target.result;
|
||||
self.db.onversionchange = function(event) {
|
||||
debug("WARNING: DB modified from a different window.");
|
||||
}
|
||||
callback(self.db);
|
||||
};
|
||||
request.onupgradeneeded = function (event) {
|
||||
debug("Database needs upgrade:" + DB_NAME + event.oldVersion + event.newVersion);
|
||||
debug("Correct new database version:" + event.newVersion == DB_VERSION);
|
||||
|
||||
let db = event.target.result;
|
||||
switch (event.oldVersion) {
|
||||
case 0:
|
||||
debug("New database");
|
||||
self.createSchema(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("No idea what to do with old database version:" + event.oldVersion);
|
||||
failureCb(event.target.errorMessage);
|
||||
break;
|
||||
}
|
||||
};
|
||||
request.onerror = function (event) {
|
||||
debug("Failed to open database:", DB_NAME);
|
||||
failureCb(event.target.errorMessage);
|
||||
};
|
||||
request.onblocked = function (event) {
|
||||
debug("Opening database request is blocked.");
|
||||
};
|
||||
},
|
||||
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
/**
|
||||
* Create the initial database schema.
|
||||
*
|
||||
@ -101,7 +44,7 @@ ContactDB.prototype = {
|
||||
* }
|
||||
*/
|
||||
createSchema: function createSchema(db) {
|
||||
let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
|
||||
let objectStore = db.createObjectStore(this.dbStoreName, {keyPath: "id"});
|
||||
|
||||
// Metadata indexes
|
||||
objectStore.createIndex("published", "published", { unique: false });
|
||||
@ -127,41 +70,6 @@ ContactDB.prototype = {
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new transaction.
|
||||
*
|
||||
* @param txn_type
|
||||
* Type of transaction (e.g. "readwrite")
|
||||
* @param callback
|
||||
* Function to call when the transaction is available. It will
|
||||
* be invoked with the transaction and the 'contacts' object store.
|
||||
* @param successCb [optional]
|
||||
* Success callback to call on a successful transaction commit.
|
||||
* @param failureCb [optional]
|
||||
* Error callback to call when an error is encountered.
|
||||
*/
|
||||
newTxn: function newTxn(txn_type, callback, successCb, failureCb) {
|
||||
this.ensureDB(function (db) {
|
||||
debug("Starting new transaction" + txn_type);
|
||||
let txn = db.transaction(STORE_NAME, txn_type);
|
||||
debug("Retrieving object store", STORE_NAME);
|
||||
let store = txn.objectStore(STORE_NAME);
|
||||
|
||||
txn.oncomplete = function (event) {
|
||||
debug("Transaction complete. Returning to callback.");
|
||||
successCb(txn.result);
|
||||
};
|
||||
|
||||
txn.onabort = function (event) {
|
||||
debug("Caught error on transaction");
|
||||
// FIXXMEE: this will work in the future. Bug 748630
|
||||
// failureCb(event.target.error.name);
|
||||
failureCb("UnknownError");
|
||||
};
|
||||
callback(txn, store);
|
||||
}, failureCb);
|
||||
},
|
||||
|
||||
makeImport: function makeImport(aContact) {
|
||||
let contact = {};
|
||||
contact.properties = {
|
||||
@ -403,5 +311,9 @@ ContactDB.prototype = {
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, STORE_NAME, aGlobal);
|
||||
}
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ let DOMContactManager = {
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._db = new ContactDB(myGlobal);
|
||||
this._db.init(myGlobal);
|
||||
|
||||
Services.obs.addObserver(this, "profile-before-change", false);
|
||||
|
||||
|
@ -36,6 +36,12 @@ Queue.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
const DB_NAME = "settings";
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = "settings";
|
||||
@ -43,74 +49,19 @@ const STORE_NAME = "settings";
|
||||
function SettingsDB() {}
|
||||
|
||||
SettingsDB.prototype = {
|
||||
|
||||
db: null,
|
||||
|
||||
close: function close() {
|
||||
if (this.db)
|
||||
this.db.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare the database. This may include opening the database and upgrading
|
||||
* it to the latest schema version.
|
||||
*
|
||||
* @return (via callback) a database ready for use.
|
||||
*/
|
||||
ensureDB: function ensureDB(aSuccessCb, aFailureCb, aGlobal) {
|
||||
if (this.db) {
|
||||
debug("ensureDB: already have a database, returning early.");
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
debug("try to open database:" + DB_NAME + " " + DB_VERSION + " " + this.db);
|
||||
let req = aGlobal.mozIndexedDB.open(DB_NAME, DB_VERSION);
|
||||
req.onsuccess = function (event) {
|
||||
debug("Opened database:", DB_NAME, DB_VERSION);
|
||||
self.db = event.target.result;
|
||||
self.db.onversionchange = function(event) {
|
||||
debug("WARNING: DB modified from a different window.");
|
||||
}
|
||||
aSuccessCb();
|
||||
};
|
||||
req.onupgradeneeded = function (aEvent) {
|
||||
debug("Database needs upgrade:" + DB_NAME + aEvent.oldVersion + aEvent.newVersion);
|
||||
debug("Correct new database version:" + aEvent.newVersion == DB_VERSION);
|
||||
|
||||
let db = aEvent.target.result;
|
||||
switch (aEvent.oldVersion) {
|
||||
case 0:
|
||||
debug("New database");
|
||||
self.createSchema(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("No idea what to do with old database version:" + aEvent.oldVersion);
|
||||
aFailureCb(aEvent.target.errorMessage);
|
||||
break;
|
||||
}
|
||||
};
|
||||
req.onerror = function (aEvent) {
|
||||
debug("Failed to open database:", DB_NAME);
|
||||
aFailureCb(aEvent.target.errorMessage);
|
||||
};
|
||||
req.onblocked = function (aEvent) {
|
||||
debug("Opening database request is blocked.");
|
||||
};
|
||||
},
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
createSchema: function createSchema(aDb) {
|
||||
let objectStore = aDb.createObjectStore(STORE_NAME, {keyPath: "settingName"});
|
||||
let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "settingName" });
|
||||
objectStore.createIndex("settingValue", "settingValue", { unique: false });
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, STORE_NAME, aGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
@ -197,11 +148,11 @@ SettingsLock.prototype = {
|
||||
},
|
||||
|
||||
createTransactionAndProcess: function() {
|
||||
if (this._settingsManager._settingsDB.db) {
|
||||
if (this._settingsManager._settingsDB._db) {
|
||||
var lock;
|
||||
while (lock = this._settingsManager._locks.dequeue()) {
|
||||
if (!lock._transaction) {
|
||||
lock._transaction = lock._settingsManager._settingsDB.db.transaction(STORE_NAME, "readwrite");
|
||||
lock._transaction = lock._settingsManager._settingsDB._db.transaction(STORE_NAME, "readwrite");
|
||||
}
|
||||
lock.process();
|
||||
}
|
||||
@ -278,6 +229,7 @@ function SettingsManager()
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._settingsDB = new SettingsDB();
|
||||
this._settingsDB.init(myGlobal);
|
||||
}
|
||||
|
||||
SettingsManager.prototype = {
|
||||
|
Loading…
Reference in New Issue
Block a user