Bug 697246: Defer creating the extensions database until it is actually necessary. r=Unfocused

This commit is contained in:
Dave Townsend 2011-11-08 16:02:49 -08:00
Родитель 31a79df660
Коммит 35820dbe1e
3 изменённых файлов: 105 добавлений и 29 удалений

Просмотреть файл

@ -2942,16 +2942,18 @@ var XPIProvider = {
let state = this.getInstallLocationStates();
// If the database exists then the previous file cache can be trusted
// otherwise the database needs to be recreated
let dbFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true);
updateDatabase |= !dbFile.exists();
if (!updateDatabase) {
// If the state has changed then we must update the database
let cache = Prefs.getCharPref(PREF_INSTALL_CACHE, null);
updateDatabase |= cache != JSON.stringify(state);
}
// If the database doesn't exist and there are add-ons installed then we
// must update the database however if there are no add-ons then there is
// no need to update the database.
if (!XPIDatabase.dbfileExists)
updateDatabase = state.length > 0;
if (!updateDatabase) {
let bootstrapDescriptors = [this.bootstrappedAddons[b].descriptor
for (b in this.bootstrappedAddons)];
@ -2963,7 +2965,7 @@ var XPIProvider = {
bootstrapDescriptors.splice(pos, 1);
}
});
if (bootstrapDescriptors.length > 0) {
WARN("Bootstrap state is invalid (missing add-ons: " + bootstrapDescriptors.toSource() + ")");
updateDatabase = true;
@ -2977,7 +2979,7 @@ var XPIProvider = {
// If the database needs to be updated then open it and then update it
// from the filesystem
if (updateDatabase || hasPendingChanges) {
let migrateData = XPIDatabase.openConnection(false);
let migrateData = XPIDatabase.openConnection(false, true);
try {
extensionListChanged = this.processFileChanges(state, manifests,
@ -4022,6 +4024,8 @@ var XPIDatabase = {
addonCache: [],
// The nested transaction count
transactionCount: 0,
// The database file
dbfile: FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true),
// The statements used by the database
statements: {
@ -4113,6 +4117,11 @@ var XPIDatabase = {
rollbackSavepoint: "ROLLBACK TO SAVEPOINT 'default'"
},
get dbfileExists() {
delete this.dbfileExists;
return this.dbfileExists = this.dbfile.exists();
},
/**
* Begins a new transaction in the database. Transactions may be nested. Data
* written by an inner transaction may be rolled back on its own. Rolling back
@ -4176,6 +4185,7 @@ var XPIDatabase = {
// Attempt to open the database
try {
connection = Services.storage.openUnsharedDatabase(aDBFile);
this.dbfileExists = true;
}
catch (e) {
ERROR("Failed to open database (1st attempt)", e);
@ -4213,12 +4223,17 @@ var XPIDatabase = {
* @return the migration data from the database if it was an old schema or
* null otherwise.
*/
openConnection: function XPIDB_openConnection(aRebuildOnError) {
this.initialized = true;
let dbfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true);
openConnection: function XPIDB_openConnection(aRebuildOnError, aForceOpen) {
delete this.connection;
this.connection = this.openDatabaseFile(dbfile);
if (!aForceOpen && !this.dbfileExists) {
this.connection = null;
return {};
}
this.initialized = true;
this.connection = this.openDatabaseFile(this.dbfile);
let migrateData = null;
// If the database was corrupt or missing then the new blank database will
@ -4235,11 +4250,11 @@ var XPIDatabase = {
// Delete the existing database
this.connection.close();
try {
if (dbfile.exists())
dbfile.remove(true);
if (this.dbfileExists)
this.dbfile.remove(true);
// Reopen an empty database
this.connection = this.openDatabaseFile(dbfile);
this.connection = this.openDatabaseFile(this.dbfile);
}
catch (e) {
ERROR("Failed to remove old database", e);
@ -4250,7 +4265,6 @@ var XPIDatabase = {
}
else if (Prefs.getIntPref(PREF_DB_SCHEMA, 0) == 0) {
// Only migrate data from the RDF if we haven't done it before
LOG("Migrating data from extensions.rdf");
migrateData = this.getMigrateDataFromRDF();
}
@ -4350,6 +4364,7 @@ var XPIDatabase = {
// Migrate data from extensions.rdf
let rdffile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_DATABASE], true);
if (rdffile.exists()) {
LOG("Migrating data from extensions.rdf");
let ds = gRDF.GetDataSourceBlocking(Services.io.newFileURI(rdffile).spec);
let root = Cc["@mozilla.org/rdf/container;1"].
createInstance(Ci.nsIRDFContainer);
@ -4963,6 +4978,9 @@ var XPIDatabase = {
* @return an array of names of install locations
*/
getInstallLocations: function XPIDB_getInstallLocations() {
if (!this.connection)
return [];
let stmt = this.getStatement("getInstallLocations");
return [row.location for each (row in resultRows(stmt))];
@ -4976,6 +4994,9 @@ var XPIDatabase = {
* @return an array of DBAddonInternals
*/
getAddonsInLocation: function XPIDB_getAddonsInLocation(aLocation) {
if (!this.connection)
return [];
let stmt = this.getStatement("getAddonsInLocation");
stmt.params.location = aLocation;
@ -4994,6 +5015,11 @@ var XPIDatabase = {
* A callback to pass the DBAddonInternal to
*/
getAddonInLocation: function XPIDB_getAddonInLocation(aId, aLocation, aCallback) {
if (!this.connection) {
aCallback(null);
return;
}
let stmt = this.getStatement("getAddonInLocation");
stmt.params.id = aId;
@ -5020,6 +5046,11 @@ var XPIDatabase = {
* A callback to pass the DBAddonInternal to
*/
getVisibleAddonForID: function XPIDB_getVisibleAddonForID(aId, aCallback) {
if (!this.connection) {
aCallback(null);
return;
}
let stmt = this.getStatement("getVisibleAddonForID");
stmt.params.id = aId;
@ -5045,6 +5076,11 @@ var XPIDatabase = {
* A callback to pass the array of DBAddonInternals to
*/
getVisibleAddons: function XPIDB_getVisibleAddons(aTypes, aCallback) {
if (!this.connection) {
aCallback([]);
return;
}
let stmt = null;
if (!aTypes || aTypes.length == 0) {
stmt = this.getStatement("getVisibleAddons");
@ -5076,6 +5112,9 @@ var XPIDatabase = {
* @return an array of DBAddonInternals
*/
getAddonsByType: function XPIDB_getAddonsByType(aType) {
if (!this.connection)
return [];
let stmt = this.getStatement("getAddonsByType");
stmt.params.type = aType;
@ -5090,6 +5129,9 @@ var XPIDatabase = {
* @return a DBAddonInternal
*/
getVisibleAddonForInternalName: function XPIDB_getVisibleAddonForInternalName(aInternalName) {
if (!this.connection)
return null;
let stmt = this.getStatement("getVisibleAddonForInternalName");
let addon = null;
@ -5112,6 +5154,11 @@ var XPIDatabase = {
*/
getVisibleAddonsWithPendingOperations:
function XPIDB_getVisibleAddonsWithPendingOperations(aTypes, aCallback) {
if (!this.connection) {
aCallback([]);
return;
}
let stmt = null;
if (!aTypes || aTypes.length == 0) {
stmt = this.getStatement("getVisibleAddonsWithPendingOperations");
@ -5143,6 +5190,9 @@ var XPIDatabase = {
* @return an array of DBAddonInternals
*/
getAddons: function XPIDB_getAddons() {
if (!this.connection)
return [];
let stmt = this.getStatement("getAddons");
return [this.makeAddonFromRow(row) for each (row in resultRows(stmt))];;
@ -5157,6 +5207,10 @@ var XPIDatabase = {
* The file descriptor of the add-on
*/
addAddonMetadata: function XPIDB_addAddonMetadata(aAddon, aDescriptor) {
// If there is no DB yet then forcibly create one
if (!this.connection)
this.openConnection(false, true);
this.beginTransaction();
var self = this;
@ -5430,28 +5484,34 @@ var XPIDatabase = {
let enabledAddons = [];
let text = "[ExtensionDirs]\r\n";
let count = 0;
let stmt;
let stmt = this.getStatement("getActiveAddons");
if (this.connection) {
stmt = this.getStatement("getActiveAddons");
for (let row in resultRows(stmt)) {
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
enabledAddons.push(row.id + ":" + row.version);
for (let row in resultRows(stmt)) {
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
enabledAddons.push(row.id + ":" + row.version);
}
}
// The selected skin may come from an inactive theme (the default theme
// when a lightweight theme is applied for example)
text += "\r\n[ThemeDirs]\r\n";
if (Prefs.getBoolPref(PREF_EM_DSS_ENABLED)) {
stmt = this.getStatement("getThemes");
}
else {
stmt = this.getStatement("getActiveTheme");
stmt.params.internalName = XPIProvider.selectedSkin;
}
count = 0;
for (let row in resultRows(stmt)) {
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
enabledAddons.push(row.id + ":" + row.version);
if (this.connection) {
if (Prefs.getBoolPref(PREF_EM_DSS_ENABLED)) {
stmt = this.getStatement("getThemes");
}
else {
stmt = this.getStatement("getActiveTheme");
stmt.params.internalName = XPIProvider.selectedSkin;
}
count = 0;
for (let row in resultRows(stmt)) {
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
enabledAddons.push(row.id + ":" + row.version);
}
}
var fos = FileUtils.openSafeFileOutputStream(addonsList);

Просмотреть файл

@ -125,6 +125,10 @@ function run_test() {
startupManager();
let file = gProfD.clone();
file.append("extensions.sqlite");
do_check_false(file.exists());
run_test_1();
}
@ -167,6 +171,10 @@ function run_test_1() {
}
function check_test_1() {
let file = gProfD.clone();
file.append("extensions.sqlite");
do_check_true(file.exists());
AddonManager.getAllInstalls(function(installs) {
// There should be no active installs now since the install completed and
// doesn't require a restart.

Просмотреть файл

@ -132,6 +132,10 @@ function run_test() {
check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []);
check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []);
let file = gProfD.clone();
file.append("extensions.sqlite");
do_check_false(file.exists());
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
"addon3@tests.mozilla.org",
@ -183,6 +187,10 @@ function run_test_1() {
check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []);
do_check_true(gCachePurged);
let file = gProfD.clone();
file.append("extensions.sqlite");
do_check_true(file.exists());
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
"addon3@tests.mozilla.org",