mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 21:00:50 +00:00
Bug 703154: Simplify the schema migration code. r=Unfocused
This commit is contained in:
parent
a065316e1a
commit
7dbfd1ac65
@ -159,6 +159,13 @@ const DB_BOOL_METADATA = ["visible", "active", "userDisabled", "appDisabled",
|
||||
"softDisabled", "foreignInstall",
|
||||
"hasBinaryComponents", "strictCompatibility"];
|
||||
|
||||
// Properties that should be migrated where possible from an old database. These
|
||||
// shouldn't include properties that can be read directly from install.rdf files
|
||||
// or calculated
|
||||
const DB_MIGRATE_METADATA= ["installDate", "userDisabled", "softDisabled",
|
||||
"sourceURI", "applyBackgroundUpdates",
|
||||
"releaseNotesURI", "foreignInstall", "syncGUID"];
|
||||
|
||||
const BOOTSTRAP_REASONS = {
|
||||
APP_STARTUP : 1,
|
||||
APP_SHUTDOWN : 2,
|
||||
@ -2643,24 +2650,17 @@ var XPIProvider = {
|
||||
// If there is migration data then apply it.
|
||||
if (aMigrateData) {
|
||||
LOG("Migrating data from old database");
|
||||
// A theme's disabled state is determined by the selected theme
|
||||
// preference which is read in loadManifestFromRDF
|
||||
if (newAddon.type != "theme")
|
||||
newAddon.userDisabled = aMigrateData.userDisabled;
|
||||
if ("syncGUID" in aMigrateData)
|
||||
newAddon.syncGUID = aMigrateData.syncGUID;
|
||||
if ("installDate" in aMigrateData)
|
||||
newAddon.installDate = aMigrateData.installDate;
|
||||
if ("softDisabled" in aMigrateData)
|
||||
newAddon.softDisabled = aMigrateData.softDisabled;
|
||||
if ("applyBackgroundUpdates" in aMigrateData)
|
||||
newAddon.applyBackgroundUpdates = aMigrateData.applyBackgroundUpdates;
|
||||
if ("sourceURI" in aMigrateData)
|
||||
newAddon.sourceURI = aMigrateData.sourceURI;
|
||||
if ("releaseNotesURI" in aMigrateData)
|
||||
newAddon.releaseNotesURI = aMigrateData.releaseNotesURI;
|
||||
if ("foreignInstall" in aMigrateData)
|
||||
newAddon.foreignInstall = aMigrateData.foreignInstall;
|
||||
|
||||
DB_MIGRATE_METADATA.forEach(function(aProp) {
|
||||
// A theme's disabled state is determined by the selected theme
|
||||
// preference which is read in loadManifestFromRDF
|
||||
if (aProp == "userDisabled" && newAddon.type == "theme")
|
||||
return;
|
||||
|
||||
LOG("Migrating " + aProp);
|
||||
if (aProp in aMigrateData)
|
||||
newAddon[aProp] = aMigrateData[aProp];
|
||||
});
|
||||
|
||||
// Some properties should only be migrated if the add-on hasn't changed.
|
||||
// The version property isn't a perfect check for this but covers the
|
||||
@ -4476,61 +4476,47 @@ var XPIDatabase = {
|
||||
// Attempt to migrate data from a different (even future!) version of the
|
||||
// database
|
||||
try {
|
||||
// Build a list of sql statements that might recover useful data from this
|
||||
// and future versions of the schema
|
||||
var sql = [];
|
||||
sql.push("SELECT internal_id, id, syncGUID, location, userDisabled, " +
|
||||
"softDisabled, installDate, version, applyBackgroundUpdates, " +
|
||||
"sourceURI, releaseNotesURI, foreignInstall FROM addon");
|
||||
sql.push("SELECT internal_id, id, location, userDisabled, " +
|
||||
"softDisabled, installDate, version, applyBackgroundUpdates, " +
|
||||
"sourceURI, releaseNotesURI, foreignInstall FROM addon");
|
||||
sql.push("SELECT internal_id, id, location, userDisabled, " +
|
||||
"softDisabled, installDate, version, applyBackgroundUpdates, " +
|
||||
"sourceURI, releaseNotesURI FROM addon");
|
||||
sql.push("SELECT internal_id, id, location, userDisabled, " +
|
||||
"installDate, version, applyBackgroundUpdates, " +
|
||||
"sourceURI, releaseNotesURI FROM addon");
|
||||
sql.push("SELECT internal_id, id, location, userDisabled, installDate, " +
|
||||
"version FROM addon");
|
||||
var stmt = this.connection.createStatement("PRAGMA table_info(addon)");
|
||||
|
||||
var stmt = null;
|
||||
if (!sql.some(function(aSql) {
|
||||
try {
|
||||
stmt = this.connection.createStatement(aSql);
|
||||
return true;
|
||||
const REQUIRED = ["internal_id", "id", "location", "userDisabled",
|
||||
"installDate", "version"];
|
||||
|
||||
let reqCount = 0;
|
||||
let props = [];
|
||||
for (let row in resultRows(stmt)) {
|
||||
if (REQUIRED.indexOf(row.name) != -1) {
|
||||
reqCount++;
|
||||
props.push(row.name);
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
else if (DB_METADATA.indexOf(row.name) != -1) {
|
||||
props.push(row.name);
|
||||
}
|
||||
}, this)) {
|
||||
else if (DB_BOOL_METADATA.indexOf(row.name) != -1) {
|
||||
props.push(row.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (reqCount < REQUIRED.length) {
|
||||
ERROR("Unable to read anything useful from the database");
|
||||
return migrateData;
|
||||
}
|
||||
stmt.finalize();
|
||||
|
||||
stmt = this.connection.createStatement("SELECT " + props.join(",") + " FROM addon");
|
||||
for (let row in resultRows(stmt)) {
|
||||
if (!(row.location in migrateData))
|
||||
migrateData[row.location] = {};
|
||||
migrateData[row.location][row.id] = {
|
||||
internal_id: row.internal_id,
|
||||
version: row.version,
|
||||
installDate: row.installDate,
|
||||
userDisabled: row.userDisabled == 1,
|
||||
let addonData = {
|
||||
targetApplications: []
|
||||
};
|
||||
}
|
||||
migrateData[row.location][row.id] = addonData;
|
||||
|
||||
if ("syncGUID" in row)
|
||||
migrateData[row.location][row.id].syncGUID = row.syncGUID;
|
||||
if ("softDisabled" in row)
|
||||
migrateData[row.location][row.id].softDisabled = row.softDisabled == 1;
|
||||
if ("applyBackgroundUpdates" in row)
|
||||
migrateData[row.location][row.id].applyBackgroundUpdates = row.applyBackgroundUpdates == 1;
|
||||
if ("sourceURI" in row)
|
||||
migrateData[row.location][row.id].sourceURI = row.sourceURI;
|
||||
if ("releaseNotesURI" in row)
|
||||
migrateData[row.location][row.id].releaseNotesURI = row.releaseNotesURI;
|
||||
if ("foreignInstall" in row)
|
||||
migrateData[row.location][row.id].foreignInstall = row.foreignInstall;
|
||||
props.forEach(function(aProp) {
|
||||
if (DB_BOOL_METADATA.indexOf(aProp) != -1)
|
||||
addonData[aProp] = row[aProp] == 1;
|
||||
else
|
||||
addonData[aProp] = row[aProp];
|
||||
})
|
||||
}
|
||||
|
||||
var taStmt = this.connection.createStatement("SELECT id, minVersion, " +
|
||||
|
@ -135,7 +135,7 @@ function run_test() {
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
db.schemaVersion = 100;
|
||||
db.schemaVersion = 10000;
|
||||
Services.prefs.setIntPref("extensions.databaseSchema", 100);
|
||||
db.close();
|
||||
|
||||
|
139
toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js
Normal file
139
toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js
Normal file
@ -0,0 +1,139 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Checks that we fail to migrate but still start up ok when there is a database
|
||||
// with no useful data in it.
|
||||
|
||||
const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
|
||||
|
||||
var addon1 = {
|
||||
id: "addon1@tests.mozilla.org",
|
||||
version: "1.0",
|
||||
name: "Test 1",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}]
|
||||
};
|
||||
|
||||
var addon2 = {
|
||||
id: "addon2@tests.mozilla.org",
|
||||
version: "2.0",
|
||||
name: "Test 5",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "0",
|
||||
maxVersion: "0"
|
||||
}]
|
||||
};
|
||||
|
||||
var defaultTheme = {
|
||||
id: "default@tests.mozilla.org",
|
||||
version: "2.0",
|
||||
name: "Default theme",
|
||||
internalName: "classic/1.0",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}]
|
||||
};
|
||||
|
||||
var theme1 = {
|
||||
id: "theme1@tests.mozilla.org",
|
||||
version: "2.0",
|
||||
name: "Test theme",
|
||||
internalName: "theme1/1.0",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}]
|
||||
};
|
||||
|
||||
const profileDir = gProfD.clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
|
||||
writeInstallRDFForExtension(addon1, profileDir);
|
||||
writeInstallRDFForExtension(addon2, profileDir);
|
||||
writeInstallRDFForExtension(defaultTheme, profileDir);
|
||||
writeInstallRDFForExtension(theme1, profileDir);
|
||||
|
||||
Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0");
|
||||
|
||||
// Write out a broken database (no userDisabled field)
|
||||
let dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
let db = AM_Cc["@mozilla.org/storage/service;1"].
|
||||
getService(AM_Ci.mozIStorageService).
|
||||
openDatabase(dbfile);
|
||||
db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"id TEXT, location TEXT, version TEXT, active INTEGER, " +
|
||||
"installDate INTEGER");
|
||||
db.createTable("targetApplication", "addon_internal_id INTEGER, " +
|
||||
"id TEXT, minVersion TEXT, maxVersion TEXT");
|
||||
let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " +
|
||||
":version, :active, :installDate)");
|
||||
|
||||
let internal_ids = {};
|
||||
|
||||
[["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0"],
|
||||
["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "0"],
|
||||
["default@tests.mozilla.org", "app-profile", "2.0", "1", "0"],
|
||||
["theme1@tests.mozilla.org", "app-profile", "2.0", "0", "0"]].forEach(function(a) {
|
||||
stmt.params.id = a[0];
|
||||
stmt.params.location = a[1];
|
||||
stmt.params.version = a[2];
|
||||
stmt.params.active = a[3];
|
||||
stmt.params.installDate = a[4];
|
||||
stmt.execute();
|
||||
internal_ids[a[0]] = db.lastInsertRowID;
|
||||
});
|
||||
stmt.finalize();
|
||||
|
||||
db.schemaVersion = 100;
|
||||
Services.prefs.setIntPref("extensions.databaseSchema", 100);
|
||||
db.close();
|
||||
|
||||
startupManager();
|
||||
check_startup_changes("installed", []);
|
||||
check_startup_changes("updated", []);
|
||||
check_startup_changes("uninstalled", []);
|
||||
check_startup_changes("disabled", []);
|
||||
check_startup_changes("enabled", []);
|
||||
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"default@tests.mozilla.org",
|
||||
"theme1@tests.mozilla.org"],
|
||||
function([a1, a2, d, t1]) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_false(a1.userDisabled);
|
||||
do_check_false(a1.appDisabled);
|
||||
do_check_true(a1.isActive);
|
||||
|
||||
do_check_neq(a2, null);
|
||||
do_check_false(a2.userDisabled);
|
||||
do_check_true(a2.appDisabled);
|
||||
do_check_false(a2.isActive);
|
||||
|
||||
// Should have enabled the selected theme
|
||||
do_check_neq(t1, null);
|
||||
do_check_false(t1.userDisabled);
|
||||
do_check_false(t1.appDisabled);
|
||||
do_check_true(t1.isActive);
|
||||
|
||||
do_check_neq(d, null);
|
||||
do_check_true(d.userDisabled);
|
||||
do_check_false(d.appDisabled);
|
||||
do_check_false(d.isActive);
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
@ -173,6 +173,7 @@ skip-if = os == "android"
|
||||
[test_migrate2.js]
|
||||
[test_migrate3.js]
|
||||
[test_migrate4.js]
|
||||
[test_migrate5.js]
|
||||
[test_migrateAddonRepository.js]
|
||||
[test_permissions.js]
|
||||
[test_plugins.js]
|
||||
|
Loading…
x
Reference in New Issue
Block a user