filer/src/providers/indexeddb.js

150 lines
4.1 KiB
JavaScript
Raw Normal View History

var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
var IDB_RW = require('../constants.js').IDB_RW;
var IDB_RO = require('../constants.js').IDB_RO;
var Errors = require('../errors.js');
var FilerBuffer = require('../buffer.js');
var indexedDB = global.indexedDB ||
global.mozIndexedDB ||
global.webkitIndexedDB ||
global.msIndexedDB;
function IndexedDBContext(db, mode) {
var transaction = db.transaction(FILE_STORE_NAME, mode);
this.objectStore = transaction.objectStore(FILE_STORE_NAME);
}
IndexedDBContext.prototype.clear = function(callback) {
try {
var request = this.objectStore.clear();
request.onsuccess = function(event) {
callback();
};
request.onerror = function(error) {
callback(error);
};
} catch(e) {
callback(e);
}
};
function _get(objectStore, key, callback) {
try {
var request = objectStore.get(key);
request.onsuccess = function onsuccess(event) {
var result = event.target.result;
callback(null, result);
};
request.onerror = function onerror(error) {
callback(error);
};
} catch(e) {
callback(e);
}
}
IndexedDBContext.prototype.getObject = function(key, callback) {
_get(this.objectStore, key, callback);
};
IndexedDBContext.prototype.getBuffer = function(key, callback) {
_get(this.objectStore, key, function(err, arrayBuffer) {
if(err) {
return callback(err);
}
callback(null, new FilerBuffer(arrayBuffer));
});
};
function _put(objectStore, key, value, callback) {
try {
var request = objectStore.put(value, key);
request.onsuccess = function onsuccess(event) {
var result = event.target.result;
callback(null, result);
};
request.onerror = function onerror(error) {
callback(error);
};
} catch(e) {
callback(e);
}
}
IndexedDBContext.prototype.putObject = function(key, value, callback) {
_put(this.objectStore, key, value, callback);
};
IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
_put(this.objectStore, key, uint8BackedBuffer.buffer, callback);
};
IndexedDBContext.prototype.delete = function(key, callback) {
try {
var request = this.objectStore.delete(key);
request.onsuccess = function onsuccess(event) {
var result = event.target.result;
callback(null, result);
};
request.onerror = function(error) {
callback(error);
};
} catch(e) {
callback(e);
}
};
function IndexedDB(name) {
this.name = name || FILE_SYSTEM_NAME;
this.db = null;
}
IndexedDB.isSupported = function() {
return !!indexedDB;
};
IndexedDB.prototype.open = function(callback) {
var that = this;
// Bail if we already have a db open
if( that.db ) {
callback(null, false);
return;
}
// Keep track of whether we're accessing this db for the first time
// and therefore needs to get formatted.
var firstAccess = false;
// NOTE: we're not using versioned databases.
var openRequest = indexedDB.open(that.name);
// If the db doesn't exist, we'll create it
openRequest.onupgradeneeded = function onupgradeneeded(event) {
var db = event.target.result;
if(db.objectStoreNames.contains(FILE_STORE_NAME)) {
db.deleteObjectStore(FILE_STORE_NAME);
}
db.createObjectStore(FILE_STORE_NAME);
firstAccess = true;
};
openRequest.onsuccess = function onsuccess(event) {
that.db = event.target.result;
callback(null, firstAccess);
};
openRequest.onerror = function onerror(error) {
callback(new Errors.EINVAL('IndexedDB cannot be accessed. If private browsing is enabled, disable it.'));
};
};
IndexedDB.prototype.getReadOnlyContext = function() {
// Due to timing issues in Chrome with readwrite vs. readonly indexeddb transactions
// always use readwrite so we can make sure pending commits finish before callbacks.
// See https://github.com/js-platform/filer/issues/128
return new IndexedDBContext(this.db, IDB_RW);
};
IndexedDB.prototype.getReadWriteContext = function() {
return new IndexedDBContext(this.db, IDB_RW);
};
module.exports = IndexedDB;