зеркало из https://github.com/mozilla/gecko-dev.git
Bug 697246: Defer creating the extensions database until it is actually necessary. r=Unfocused
This commit is contained in:
Родитель
31a79df660
Коммит
35820dbe1e
|
@ -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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче