filer/src/providers/websql.js

161 lines
5.3 KiB
JavaScript

define(function(require) {
var FILE_SYSTEM_NAME = require('src/constants').FILE_SYSTEM_NAME;
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME;
var WSQL_VERSION = require('src/constants').WSQL_VERSION;
var WSQL_SIZE = require('src/constants').WSQL_SIZE;
var WSQL_DESC = require('src/constants').WSQL_DESC;
var u8toArray = require('src/shared').u8toArray;
var Errors = require('src/errors');
function WebSQLContext(db, isReadOnly) {
var that = this;
this.getTransaction = function(callback) {
if(that.transaction) {
callback(that.transaction);
return;
}
// Either do readTransaction() (read-only) or transaction() (read/write)
db[isReadOnly ? 'readTransaction' : 'transaction'](function(transaction) {
that.transaction = transaction;
callback(transaction);
});
};
}
WebSQLContext.prototype.clear = function(callback) {
function onError(transaction, error) {
callback(error);
}
function onSuccess(transaction, result) {
callback(null);
}
this.getTransaction(function(transaction) {
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + ";",
[], onSuccess, onError);
});
};
WebSQLContext.prototype.get = function(key, callback) {
function onSuccess(transaction, result) {
// If the key isn't found, return null
var value = result.rows.length === 0 ? null : result.rows.item(0).data;
try {
if(value) {
value = JSON.parse(value);
// Deal with special-cased flattened typed arrays in WebSQL (see put() below)
if(value.__isUint8Array) {
value = new Uint8Array(value.__array);
}
}
callback(null, value);
} catch(e) {
callback(e);
}
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("SELECT data FROM " + FILE_STORE_NAME + " WHERE id = ?;",
[key], onSuccess, onError);
});
};
WebSQLContext.prototype.put = function(key, value, callback) {
// We do extra work to make sure typed arrays survive
// being stored in the db and still get the right prototype later.
if(Object.prototype.toString.call(value) === "[object Uint8Array]") {
value = {
__isUint8Array: true,
__array: u8toArray(value)
};
}
value = JSON.stringify(value);
function onSuccess(transaction, result) {
callback(null);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("INSERT OR REPLACE INTO " + FILE_STORE_NAME + " (id, data) VALUES (?, ?);",
[key, value], onSuccess, onError);
});
};
WebSQLContext.prototype.delete = function(key, callback) {
function onSuccess(transaction, result) {
callback(null);
}
function onError(transaction, error) {
callback(error);
}
this.getTransaction(function(transaction) {
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + " WHERE id = ?;",
[key], onSuccess, onError);
});
};
function WebSQL(name) {
this.name = name || FILE_SYSTEM_NAME;
this.db = null;
}
WebSQL.isSupported = function() {
return typeof window === 'undefined' ? false : !!window.openDatabase;
};
WebSQL.prototype.open = function(callback) {
var that = this;
// Bail if we already have a db open
if(that.db) {
callback(null, false);
return;
}
var db = window.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE);
if(!db) {
callback("[WebSQL] Unable to open database.");
return;
}
function onError(transaction, error) {
if (error.code === 5) {
callback(new Errors.EINVAL('WebSQL cannot be accessed. If private browsing is enabled, disable it.'));
}
callback(error);
}
function onSuccess(transaction, result) {
that.db = db;
function gotCount(transaction, result) {
var firstAccess = result.rows.item(0).count === 0;
callback(null, firstAccess);
}
function onError(transaction, error) {
callback(error);
}
// Keep track of whether we're accessing this db for the first time
// and therefore needs to get formatted.
transaction.executeSql("SELECT COUNT(id) AS count FROM " + FILE_STORE_NAME + ";",
[], gotCount, onError);
}
// Create the table and index we'll need to store the fs data.
db.transaction(function(transaction) {
function createIndex(transaction) {
transaction.executeSql("CREATE INDEX IF NOT EXISTS idx_" + FILE_STORE_NAME + "_id" +
" on " + FILE_STORE_NAME + " (id);",
[], onSuccess, onError);
}
transaction.executeSql("CREATE TABLE IF NOT EXISTS " + FILE_STORE_NAME + " (id unique, data TEXT);",
[], createIndex, onError);
});
};
WebSQL.prototype.getReadOnlyContext = function() {
return new WebSQLContext(this.db, true);
};
WebSQL.prototype.getReadWriteContext = function() {
return new WebSQLContext(this.db, false);
};
return WebSQL;
});