1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-07-19 03:05:22 +02:00

hardening sqlite code

This commit is contained in:
gorhill 2015-05-28 14:49:01 -04:00
parent 4c9d3f63f2
commit c285ace7d8

View File

@ -103,14 +103,14 @@ vAPI.storage = (function() {
if ( db === null ) { if ( db === null ) {
return; return;
} }
db.createStatement('VACUUM').executeAsync(); db.createAsyncStatement('VACUUM').executeAsync();
db.asyncClose(); db.asyncClose();
db = null; db = null;
}; };
var open = function() { var open = function() {
if ( db !== null ) { if ( db !== null ) {
return; return db;
} }
// Create path // Create path
@ -125,7 +125,18 @@ vAPI.storage = (function() {
path.append(location.host + '.sqlite'); path.append(location.host + '.sqlite');
// Open database // Open database
db = Services.storage.openDatabase(path); try {
db = Services.storage.openDatabase(path);
if ( db.connectionReady === false ) {
db.asyncClose();
db = null;
}
} catch (ex) {
}
if ( db === null ) {
return null;
}
// Database was opened, register cleanup task // Database was opened, register cleanup task
cleanupTasks.push(close); cleanupTasks.push(close);
@ -133,6 +144,8 @@ vAPI.storage = (function() {
// Setup database // Setup database
db.createAsyncStatement('CREATE TABLE IF NOT EXISTS settings(name TEXT PRIMARY KEY NOT NULL, value TEXT);') db.createAsyncStatement('CREATE TABLE IF NOT EXISTS settings(name TEXT PRIMARY KEY NOT NULL, value TEXT);')
.executeAsync(); .executeAsync();
return db;
}; };
// Execute a query // Execute a query
@ -160,6 +173,10 @@ vAPI.storage = (function() {
}, },
handleError: function(error) { handleError: function(error) {
console.error('SQLite error ', error.result, error.message); console.error('SQLite error ', error.result, error.message);
// Caller expects an answer regardless of failure.
if ( typeof callback === 'function' ) {
callback(null);
}
} }
}); });
}; };
@ -179,10 +196,13 @@ vAPI.storage = (function() {
}; };
var clear = function(callback) { var clear = function(callback) {
if ( db === null ) { if ( open() === null ) {
open(); if ( typeof callback === 'function' ) {
callback();
}
return;
} }
runStatement(db.createStatement('DELETE FROM settings; VACUUM;'), callback); runStatement(db.createAsyncStatement('DELETE FROM settings; VACUUM;'), callback);
}; };
var getBytesInUse = function(keys, callback) { var getBytesInUse = function(keys, callback) {
@ -190,16 +210,17 @@ vAPI.storage = (function() {
return; return;
} }
if ( db === null ) { if ( open() === null ) {
open(); callback(0);
return;
} }
var stmt; var stmt;
if ( Array.isArray(keys) ) { if ( Array.isArray(keys) ) {
stmt = db.createStatement('SELECT "size" AS size, SUM(LENGTH(value)) FROM settings WHERE name = :name'); stmt = db.createAsyncStatement('SELECT "size" AS size, SUM(LENGTH(value)) FROM settings WHERE name = :name');
bindNames(keys); bindNames(keys);
} else { } else {
stmt = db.createStatement('SELECT "size" AS size, SUM(LENGTH(value)) FROM settings'); stmt = db.createAsyncStatement('SELECT "size" AS size, SUM(LENGTH(value)) FROM settings');
} }
runStatement(stmt, function(result) { runStatement(stmt, function(result) {
@ -212,8 +233,27 @@ vAPI.storage = (function() {
return; return;
} }
if ( db === null ) { var prepareResult = function(result) {
open(); var key;
for ( key in result ) {
if ( result.hasOwnProperty(key) === false ) {
continue;
}
result[key] = JSON.parse(result[key]);
}
if ( typeof details === 'object' && details !== null ) {
for ( key in details ) {
if ( result.hasOwnProperty(key) === false ) {
result[key] = details[key];
}
}
}
callback(result);
};
if ( open() === null ) {
prepareResult({});
return;
} }
var names = []; var names = [];
@ -229,43 +269,36 @@ vAPI.storage = (function() {
var stmt; var stmt;
if ( names.length === 0 ) { if ( names.length === 0 ) {
stmt = db.createStatement('SELECT * FROM settings'); stmt = db.createAsyncStatement('SELECT * FROM settings');
} else { } else {
stmt = db.createStatement('SELECT * FROM settings WHERE name = :name'); stmt = db.createAsyncStatement('SELECT * FROM settings WHERE name = :name');
bindNames(stmt, names); bindNames(stmt, names);
} }
runStatement(stmt, function(result) { runStatement(stmt, prepareResult);
var key;
for ( key in result ) {
result[key] = JSON.parse(result[key]);
}
if ( typeof details === 'object' && details !== null ) {
for ( key in details ) {
if ( result.hasOwnProperty(key) === false ) {
result[key] = details[key];
}
}
}
callback(result);
});
}; };
var remove = function(keys, callback) { var remove = function(keys, callback) {
if ( db === null ) { if ( open() === null ) {
open(); if ( typeof callback === 'function' ) {
callback();
}
return;
} }
var stmt = db.createStatement('DELETE FROM settings WHERE name = :name'); var stmt = db.createAsyncStatement('DELETE FROM settings WHERE name = :name');
bindNames(stmt, typeof keys === 'string' ? [keys] : keys); bindNames(stmt, typeof keys === 'string' ? [keys] : keys);
runStatement(stmt, callback); runStatement(stmt, callback);
}; };
var write = function(details, callback) { var write = function(details, callback) {
if ( db === null ) { if ( open() === null ) {
open(); if ( typeof callback === 'function' ) {
callback();
}
return;
} }
var stmt = db.createStatement('INSERT OR REPLACE INTO settings (name, value) VALUES(:name, :value)'); var stmt = db.createAsyncStatement('INSERT OR REPLACE INTO settings (name, value) VALUES(:name, :value)');
var params = stmt.newBindingParamsArray(), bp; var params = stmt.newBindingParamsArray(), bp;
for ( var key in details ) { for ( var key in details ) {
if ( details.hasOwnProperty(key) === false ) { if ( details.hasOwnProperty(key) === false ) {
@ -1080,6 +1113,7 @@ var httpObserver = {
this.tabId = 0; this.tabId = 0;
this._key = ''; // key is url, from URI.spec this._key = ''; // key is url, from URI.spec
}, },
// If all work fine, this map should not grow indefinitely. It can have // If all work fine, this map should not grow indefinitely. It can have
// stale items in it, but these will be taken care of when entries in // stale items in it, but these will be taken care of when entries in
// the ring buffer are overwritten. // the ring buffer are overwritten.
@ -1094,6 +1128,7 @@ var httpObserver = {
this.pendingRingBuffer[i] = new this.PendingRequest(); this.pendingRingBuffer[i] = new this.PendingRequest();
} }
}, },
createPendingRequest: function(url) { createPendingRequest: function(url) {
var bucket; var bucket;
var i = this.pendingWritePointer; var i = this.pendingWritePointer;
@ -1126,6 +1161,7 @@ var httpObserver = {
preq._key = url; preq._key = url;
return preq; return preq;
}, },
lookupPendingRequest: function(url) { lookupPendingRequest: function(url) {
var i = this.pendingURLToIndex.get(url); var i = this.pendingURLToIndex.get(url);
if ( i === undefined ) { if ( i === undefined ) {
@ -1232,6 +1268,7 @@ var httpObserver = {
parentFrameId: channelData[1], parentFrameId: channelData[1],
responseHeaders: result ? [{name: topic, value: result}] : [], responseHeaders: result ? [{name: topic, value: result}] : [],
tabId: channelData[3], tabId: channelData[3],
type: this.typeMap[channelData[4]] || 'other',
url: URI.asciiSpec url: URI.asciiSpec
}); });
@ -1402,6 +1439,11 @@ vAPI.net.registerListeners = function() {
var browser = e.target; var browser = e.target;
var tabId = vAPI.tabs.getTabId(browser); var tabId = vAPI.tabs.getTabId(browser);
// Ignore notifications related to our popup
if ( details.url.lastIndexOf(vAPI.getURL('popup.html'), 0) === 0 ) {
return;
}
//console.debug("nsIWebProgressListener: onLocationChange: " + details.url + " (" + details.flags + ")"); //console.debug("nsIWebProgressListener: onLocationChange: " + details.url + " (" + details.flags + ")");
// LOCATION_CHANGE_SAME_DOCUMENT = "did not load a new document" // LOCATION_CHANGE_SAME_DOCUMENT = "did not load a new document"