зеркало из 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();
|
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 (!updateDatabase) {
|
||||||
// If the state has changed then we must update the database
|
// If the state has changed then we must update the database
|
||||||
let cache = Prefs.getCharPref(PREF_INSTALL_CACHE, null);
|
let cache = Prefs.getCharPref(PREF_INSTALL_CACHE, null);
|
||||||
updateDatabase |= cache != JSON.stringify(state);
|
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) {
|
if (!updateDatabase) {
|
||||||
let bootstrapDescriptors = [this.bootstrappedAddons[b].descriptor
|
let bootstrapDescriptors = [this.bootstrappedAddons[b].descriptor
|
||||||
for (b in this.bootstrappedAddons)];
|
for (b in this.bootstrappedAddons)];
|
||||||
|
@ -2963,7 +2965,7 @@ var XPIProvider = {
|
||||||
bootstrapDescriptors.splice(pos, 1);
|
bootstrapDescriptors.splice(pos, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (bootstrapDescriptors.length > 0) {
|
if (bootstrapDescriptors.length > 0) {
|
||||||
WARN("Bootstrap state is invalid (missing add-ons: " + bootstrapDescriptors.toSource() + ")");
|
WARN("Bootstrap state is invalid (missing add-ons: " + bootstrapDescriptors.toSource() + ")");
|
||||||
updateDatabase = true;
|
updateDatabase = true;
|
||||||
|
@ -2977,7 +2979,7 @@ var XPIProvider = {
|
||||||
// If the database needs to be updated then open it and then update it
|
// If the database needs to be updated then open it and then update it
|
||||||
// from the filesystem
|
// from the filesystem
|
||||||
if (updateDatabase || hasPendingChanges) {
|
if (updateDatabase || hasPendingChanges) {
|
||||||
let migrateData = XPIDatabase.openConnection(false);
|
let migrateData = XPIDatabase.openConnection(false, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
extensionListChanged = this.processFileChanges(state, manifests,
|
extensionListChanged = this.processFileChanges(state, manifests,
|
||||||
|
@ -4022,6 +4024,8 @@ var XPIDatabase = {
|
||||||
addonCache: [],
|
addonCache: [],
|
||||||
// The nested transaction count
|
// The nested transaction count
|
||||||
transactionCount: 0,
|
transactionCount: 0,
|
||||||
|
// The database file
|
||||||
|
dbfile: FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true),
|
||||||
|
|
||||||
// The statements used by the database
|
// The statements used by the database
|
||||||
statements: {
|
statements: {
|
||||||
|
@ -4113,6 +4117,11 @@ var XPIDatabase = {
|
||||||
rollbackSavepoint: "ROLLBACK TO SAVEPOINT 'default'"
|
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
|
* 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
|
* 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
|
// Attempt to open the database
|
||||||
try {
|
try {
|
||||||
connection = Services.storage.openUnsharedDatabase(aDBFile);
|
connection = Services.storage.openUnsharedDatabase(aDBFile);
|
||||||
|
this.dbfileExists = true;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
ERROR("Failed to open database (1st attempt)", 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
|
* @return the migration data from the database if it was an old schema or
|
||||||
* null otherwise.
|
* null otherwise.
|
||||||
*/
|
*/
|
||||||
openConnection: function XPIDB_openConnection(aRebuildOnError) {
|
openConnection: function XPIDB_openConnection(aRebuildOnError, aForceOpen) {
|
||||||
this.initialized = true;
|
|
||||||
let dbfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true);
|
|
||||||
delete this.connection;
|
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;
|
let migrateData = null;
|
||||||
// If the database was corrupt or missing then the new blank database will
|
// If the database was corrupt or missing then the new blank database will
|
||||||
|
@ -4235,11 +4250,11 @@ var XPIDatabase = {
|
||||||
// Delete the existing database
|
// Delete the existing database
|
||||||
this.connection.close();
|
this.connection.close();
|
||||||
try {
|
try {
|
||||||
if (dbfile.exists())
|
if (this.dbfileExists)
|
||||||
dbfile.remove(true);
|
this.dbfile.remove(true);
|
||||||
|
|
||||||
// Reopen an empty database
|
// Reopen an empty database
|
||||||
this.connection = this.openDatabaseFile(dbfile);
|
this.connection = this.openDatabaseFile(this.dbfile);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
ERROR("Failed to remove old database", e);
|
ERROR("Failed to remove old database", e);
|
||||||
|
@ -4250,7 +4265,6 @@ var XPIDatabase = {
|
||||||
}
|
}
|
||||||
else if (Prefs.getIntPref(PREF_DB_SCHEMA, 0) == 0) {
|
else if (Prefs.getIntPref(PREF_DB_SCHEMA, 0) == 0) {
|
||||||
// Only migrate data from the RDF if we haven't done it before
|
// Only migrate data from the RDF if we haven't done it before
|
||||||
LOG("Migrating data from extensions.rdf");
|
|
||||||
migrateData = this.getMigrateDataFromRDF();
|
migrateData = this.getMigrateDataFromRDF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4350,6 +4364,7 @@ var XPIDatabase = {
|
||||||
// Migrate data from extensions.rdf
|
// Migrate data from extensions.rdf
|
||||||
let rdffile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_DATABASE], true);
|
let rdffile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_DATABASE], true);
|
||||||
if (rdffile.exists()) {
|
if (rdffile.exists()) {
|
||||||
|
LOG("Migrating data from extensions.rdf");
|
||||||
let ds = gRDF.GetDataSourceBlocking(Services.io.newFileURI(rdffile).spec);
|
let ds = gRDF.GetDataSourceBlocking(Services.io.newFileURI(rdffile).spec);
|
||||||
let root = Cc["@mozilla.org/rdf/container;1"].
|
let root = Cc["@mozilla.org/rdf/container;1"].
|
||||||
createInstance(Ci.nsIRDFContainer);
|
createInstance(Ci.nsIRDFContainer);
|
||||||
|
@ -4963,6 +4978,9 @@ var XPIDatabase = {
|
||||||
* @return an array of names of install locations
|
* @return an array of names of install locations
|
||||||
*/
|
*/
|
||||||
getInstallLocations: function XPIDB_getInstallLocations() {
|
getInstallLocations: function XPIDB_getInstallLocations() {
|
||||||
|
if (!this.connection)
|
||||||
|
return [];
|
||||||
|
|
||||||
let stmt = this.getStatement("getInstallLocations");
|
let stmt = this.getStatement("getInstallLocations");
|
||||||
|
|
||||||
return [row.location for each (row in resultRows(stmt))];
|
return [row.location for each (row in resultRows(stmt))];
|
||||||
|
@ -4976,6 +4994,9 @@ var XPIDatabase = {
|
||||||
* @return an array of DBAddonInternals
|
* @return an array of DBAddonInternals
|
||||||
*/
|
*/
|
||||||
getAddonsInLocation: function XPIDB_getAddonsInLocation(aLocation) {
|
getAddonsInLocation: function XPIDB_getAddonsInLocation(aLocation) {
|
||||||
|
if (!this.connection)
|
||||||
|
return [];
|
||||||
|
|
||||||
let stmt = this.getStatement("getAddonsInLocation");
|
let stmt = this.getStatement("getAddonsInLocation");
|
||||||
|
|
||||||
stmt.params.location = aLocation;
|
stmt.params.location = aLocation;
|
||||||
|
@ -4994,6 +5015,11 @@ var XPIDatabase = {
|
||||||
* A callback to pass the DBAddonInternal to
|
* A callback to pass the DBAddonInternal to
|
||||||
*/
|
*/
|
||||||
getAddonInLocation: function XPIDB_getAddonInLocation(aId, aLocation, aCallback) {
|
getAddonInLocation: function XPIDB_getAddonInLocation(aId, aLocation, aCallback) {
|
||||||
|
if (!this.connection) {
|
||||||
|
aCallback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let stmt = this.getStatement("getAddonInLocation");
|
let stmt = this.getStatement("getAddonInLocation");
|
||||||
|
|
||||||
stmt.params.id = aId;
|
stmt.params.id = aId;
|
||||||
|
@ -5020,6 +5046,11 @@ var XPIDatabase = {
|
||||||
* A callback to pass the DBAddonInternal to
|
* A callback to pass the DBAddonInternal to
|
||||||
*/
|
*/
|
||||||
getVisibleAddonForID: function XPIDB_getVisibleAddonForID(aId, aCallback) {
|
getVisibleAddonForID: function XPIDB_getVisibleAddonForID(aId, aCallback) {
|
||||||
|
if (!this.connection) {
|
||||||
|
aCallback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let stmt = this.getStatement("getVisibleAddonForID");
|
let stmt = this.getStatement("getVisibleAddonForID");
|
||||||
|
|
||||||
stmt.params.id = aId;
|
stmt.params.id = aId;
|
||||||
|
@ -5045,6 +5076,11 @@ var XPIDatabase = {
|
||||||
* A callback to pass the array of DBAddonInternals to
|
* A callback to pass the array of DBAddonInternals to
|
||||||
*/
|
*/
|
||||||
getVisibleAddons: function XPIDB_getVisibleAddons(aTypes, aCallback) {
|
getVisibleAddons: function XPIDB_getVisibleAddons(aTypes, aCallback) {
|
||||||
|
if (!this.connection) {
|
||||||
|
aCallback([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let stmt = null;
|
let stmt = null;
|
||||||
if (!aTypes || aTypes.length == 0) {
|
if (!aTypes || aTypes.length == 0) {
|
||||||
stmt = this.getStatement("getVisibleAddons");
|
stmt = this.getStatement("getVisibleAddons");
|
||||||
|
@ -5076,6 +5112,9 @@ var XPIDatabase = {
|
||||||
* @return an array of DBAddonInternals
|
* @return an array of DBAddonInternals
|
||||||
*/
|
*/
|
||||||
getAddonsByType: function XPIDB_getAddonsByType(aType) {
|
getAddonsByType: function XPIDB_getAddonsByType(aType) {
|
||||||
|
if (!this.connection)
|
||||||
|
return [];
|
||||||
|
|
||||||
let stmt = this.getStatement("getAddonsByType");
|
let stmt = this.getStatement("getAddonsByType");
|
||||||
|
|
||||||
stmt.params.type = aType;
|
stmt.params.type = aType;
|
||||||
|
@ -5090,6 +5129,9 @@ var XPIDatabase = {
|
||||||
* @return a DBAddonInternal
|
* @return a DBAddonInternal
|
||||||
*/
|
*/
|
||||||
getVisibleAddonForInternalName: function XPIDB_getVisibleAddonForInternalName(aInternalName) {
|
getVisibleAddonForInternalName: function XPIDB_getVisibleAddonForInternalName(aInternalName) {
|
||||||
|
if (!this.connection)
|
||||||
|
return null;
|
||||||
|
|
||||||
let stmt = this.getStatement("getVisibleAddonForInternalName");
|
let stmt = this.getStatement("getVisibleAddonForInternalName");
|
||||||
|
|
||||||
let addon = null;
|
let addon = null;
|
||||||
|
@ -5112,6 +5154,11 @@ var XPIDatabase = {
|
||||||
*/
|
*/
|
||||||
getVisibleAddonsWithPendingOperations:
|
getVisibleAddonsWithPendingOperations:
|
||||||
function XPIDB_getVisibleAddonsWithPendingOperations(aTypes, aCallback) {
|
function XPIDB_getVisibleAddonsWithPendingOperations(aTypes, aCallback) {
|
||||||
|
if (!this.connection) {
|
||||||
|
aCallback([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let stmt = null;
|
let stmt = null;
|
||||||
if (!aTypes || aTypes.length == 0) {
|
if (!aTypes || aTypes.length == 0) {
|
||||||
stmt = this.getStatement("getVisibleAddonsWithPendingOperations");
|
stmt = this.getStatement("getVisibleAddonsWithPendingOperations");
|
||||||
|
@ -5143,6 +5190,9 @@ var XPIDatabase = {
|
||||||
* @return an array of DBAddonInternals
|
* @return an array of DBAddonInternals
|
||||||
*/
|
*/
|
||||||
getAddons: function XPIDB_getAddons() {
|
getAddons: function XPIDB_getAddons() {
|
||||||
|
if (!this.connection)
|
||||||
|
return [];
|
||||||
|
|
||||||
let stmt = this.getStatement("getAddons");
|
let stmt = this.getStatement("getAddons");
|
||||||
|
|
||||||
return [this.makeAddonFromRow(row) for each (row in resultRows(stmt))];;
|
return [this.makeAddonFromRow(row) for each (row in resultRows(stmt))];;
|
||||||
|
@ -5157,6 +5207,10 @@ var XPIDatabase = {
|
||||||
* The file descriptor of the add-on
|
* The file descriptor of the add-on
|
||||||
*/
|
*/
|
||||||
addAddonMetadata: function XPIDB_addAddonMetadata(aAddon, aDescriptor) {
|
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();
|
this.beginTransaction();
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -5430,28 +5484,34 @@ var XPIDatabase = {
|
||||||
let enabledAddons = [];
|
let enabledAddons = [];
|
||||||
let text = "[ExtensionDirs]\r\n";
|
let text = "[ExtensionDirs]\r\n";
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
let stmt;
|
||||||
|
|
||||||
let stmt = this.getStatement("getActiveAddons");
|
if (this.connection) {
|
||||||
|
stmt = this.getStatement("getActiveAddons");
|
||||||
|
|
||||||
for (let row in resultRows(stmt)) {
|
for (let row in resultRows(stmt)) {
|
||||||
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
|
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
|
||||||
enabledAddons.push(row.id + ":" + row.version);
|
enabledAddons.push(row.id + ":" + row.version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The selected skin may come from an inactive theme (the default theme
|
// The selected skin may come from an inactive theme (the default theme
|
||||||
// when a lightweight theme is applied for example)
|
// when a lightweight theme is applied for example)
|
||||||
text += "\r\n[ThemeDirs]\r\n";
|
text += "\r\n[ThemeDirs]\r\n";
|
||||||
if (Prefs.getBoolPref(PREF_EM_DSS_ENABLED)) {
|
|
||||||
stmt = this.getStatement("getThemes");
|
if (this.connection) {
|
||||||
}
|
if (Prefs.getBoolPref(PREF_EM_DSS_ENABLED)) {
|
||||||
else {
|
stmt = this.getStatement("getThemes");
|
||||||
stmt = this.getStatement("getActiveTheme");
|
}
|
||||||
stmt.params.internalName = XPIProvider.selectedSkin;
|
else {
|
||||||
}
|
stmt = this.getStatement("getActiveTheme");
|
||||||
count = 0;
|
stmt.params.internalName = XPIProvider.selectedSkin;
|
||||||
for (let row in resultRows(stmt)) {
|
}
|
||||||
text += "Extension" + (count++) + "=" + row.descriptor + "\r\n";
|
count = 0;
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fos = FileUtils.openSafeFileOutputStream(addonsList);
|
var fos = FileUtils.openSafeFileOutputStream(addonsList);
|
||||||
|
|
|
@ -125,6 +125,10 @@ function run_test() {
|
||||||
|
|
||||||
startupManager();
|
startupManager();
|
||||||
|
|
||||||
|
let file = gProfD.clone();
|
||||||
|
file.append("extensions.sqlite");
|
||||||
|
do_check_false(file.exists());
|
||||||
|
|
||||||
run_test_1();
|
run_test_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +171,10 @@ function run_test_1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_test_1() {
|
function check_test_1() {
|
||||||
|
let file = gProfD.clone();
|
||||||
|
file.append("extensions.sqlite");
|
||||||
|
do_check_true(file.exists());
|
||||||
|
|
||||||
AddonManager.getAllInstalls(function(installs) {
|
AddonManager.getAllInstalls(function(installs) {
|
||||||
// There should be no active installs now since the install completed and
|
// There should be no active installs now since the install completed and
|
||||||
// doesn't require a restart.
|
// 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_DISABLED, []);
|
||||||
check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []);
|
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",
|
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||||
"addon2@tests.mozilla.org",
|
"addon2@tests.mozilla.org",
|
||||||
"addon3@tests.mozilla.org",
|
"addon3@tests.mozilla.org",
|
||||||
|
@ -183,6 +187,10 @@ function run_test_1() {
|
||||||
check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []);
|
check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []);
|
||||||
do_check_true(gCachePurged);
|
do_check_true(gCachePurged);
|
||||||
|
|
||||||
|
let file = gProfD.clone();
|
||||||
|
file.append("extensions.sqlite");
|
||||||
|
do_check_true(file.exists());
|
||||||
|
|
||||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||||
"addon2@tests.mozilla.org",
|
"addon2@tests.mozilla.org",
|
||||||
"addon3@tests.mozilla.org",
|
"addon3@tests.mozilla.org",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче