Bug 579170: DB migration can apply compatibility information to the wrong version of an add-on. r=robstrong

This commit is contained in:
Dave Townsend 2010-07-16 14:33:00 -07:00
parent 590aa51e71
commit 6b3dabd7b5
4 changed files with 96 additions and 19 deletions

View File

@ -1586,9 +1586,15 @@ var XPIProvider = {
newAddon.userDisabled = aMigrateData.userDisabled; newAddon.userDisabled = aMigrateData.userDisabled;
if ("installDate" in aMigrateData) if ("installDate" in aMigrateData)
newAddon.installDate = aMigrateData.installDate; newAddon.installDate = aMigrateData.installDate;
// 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
// vast majority of cases.
if (aMigrateData.version == newAddon.version) {
if ("targetApplications" in aMigrateData) if ("targetApplications" in aMigrateData)
newAddon.applyCompatibilityUpdate(aMigrateData, true); newAddon.applyCompatibilityUpdate(aMigrateData, true);
} }
}
try { try {
// Update the database. // Update the database.
@ -2777,6 +2783,7 @@ var XPIDatabase = {
migrateData[location] = {}; migrateData[location] = {};
let id = source.ValueUTF8.substring(PREFIX_ITEM_URI.length); let id = source.ValueUTF8.substring(PREFIX_ITEM_URI.length);
migrateData[location][id] = { migrateData[location][id] = {
version: getRDFProperty(ds, source, "version"),
userDisabled: false, userDisabled: false,
targetApplications: [] targetApplications: []
} }
@ -2807,12 +2814,14 @@ var XPIDatabase = {
try { try {
var stmt = this.connection.createStatement("SELECT internal_id, id, " + var stmt = this.connection.createStatement("SELECT internal_id, id, " +
"location, userDisabled, " + "location, userDisabled, " +
"installDate FROM addon"); "installDate, version " +
"FROM addon");
for (let row in resultRows(stmt)) { for (let row in resultRows(stmt)) {
if (!(row.location in migrateData)) if (!(row.location in migrateData))
migrateData[row.location] = {}; migrateData[row.location] = {};
migrateData[row.location][row.id] = { migrateData[row.location][row.id] = {
internal_id: row.internal_id, internal_id: row.internal_id,
version: row.version,
installDate: row.installDate, installDate: row.installDate,
userDisabled: row.userDisabled == 1, userDisabled: row.userDisabled == 1,
targetApplications: [] targetApplications: []

View File

@ -5,7 +5,8 @@
was pending user disable at the next restart and addon4 was pending user was pending user disable at the next restart and addon4 was pending user
enable at the next restart. Additionally addon1 and 2 have had enable at the next restart. Additionally addon1 and 2 have had
compatibility updates applies to make them compatible with the app and compatibility updates applies to make them compatible with the app and
toolkit respectively, addon3 and 4 have not. toolkit respectively, addon3 and 4 have not. addon5 is disabled however
at the same time as the migration a new version should be detected.
It also contains two themes in the profile --> It also contains two themes in the profile -->
<RDF:RDF xmlns:NS1="http://www.mozilla.org/2004/em-rdf#" <RDF:RDF xmlns:NS1="http://www.mozilla.org/2004/em-rdf#"
@ -35,6 +36,10 @@
NS1:id="toolkit@mozilla.org" NS1:id="toolkit@mozilla.org"
NS1:minVersion="1" NS1:minVersion="1"
NS1:maxVersion="2" /> NS1:maxVersion="2" />
<RDF:Description RDF:about="rdf:#$w8dNC7"
NS1:id="toolkit@mozilla.org"
NS1:minVersion="1"
NS1:maxVersion="2" />
<RDF:Description RDF:about="rdf:#$oadNC1" <RDF:Description RDF:about="rdf:#$oadNC1"
NS1:id="xpcshell@tests.mozilla.org" NS1:id="xpcshell@tests.mozilla.org"
NS1:minVersion="1" NS1:minVersion="1"
@ -70,6 +75,14 @@
<NS1:type NC:parseType="Integer">2</NS1:type> <NS1:type NC:parseType="Integer">2</NS1:type>
<NS1:targetApplication RDF:resource="rdf:#$w8dNC2"/> <NS1:targetApplication RDF:resource="rdf:#$w8dNC2"/>
</RDF:Description> </RDF:Description>
<RDF:Description RDF:about="urn:mozilla:item:addon5@tests.mozilla.org"
NS1:installLocation="app-profile"
NS1:version="1.0"
NS1:name="Test 5"
NS1:userDisabled="true">
<NS1:type NC:parseType="Integer">2</NS1:type>
<NS1:targetApplication RDF:resource="rdf:#$w8dNC7"/>
</RDF:Description>
<RDF:Description RDF:about="urn:mozilla:item:theme1@tests.mozilla.org" <RDF:Description RDF:about="urn:mozilla:item:theme1@tests.mozilla.org"
NS1:installLocation="app-profile" NS1:installLocation="app-profile"
NS1:version="1.0" NS1:version="1.0"
@ -91,6 +104,7 @@
<RDF:li RDF:resource="urn:mozilla:item:addon2@tests.mozilla.org"/> <RDF:li RDF:resource="urn:mozilla:item:addon2@tests.mozilla.org"/>
<RDF:li RDF:resource="urn:mozilla:item:addon3@tests.mozilla.org"/> <RDF:li RDF:resource="urn:mozilla:item:addon3@tests.mozilla.org"/>
<RDF:li RDF:resource="urn:mozilla:item:addon4@tests.mozilla.org"/> <RDF:li RDF:resource="urn:mozilla:item:addon4@tests.mozilla.org"/>
<RDF:li RDF:resource="urn:mozilla:item:addon5@tests.mozilla.org"/>
<RDF:li RDF:resource="urn:mozilla:item:theme1@tests.mozilla.org"/> <RDF:li RDF:resource="urn:mozilla:item:theme1@tests.mozilla.org"/>
<RDF:li RDF:resource="urn:mozilla:item:theme2@tests.mozilla.org"/> <RDF:li RDF:resource="urn:mozilla:item:theme2@tests.mozilla.org"/>
</RDF:Seq> </RDF:Seq>

View File

@ -48,6 +48,17 @@ var addon4 = {
}] }]
}; };
var addon5 = {
id: "addon5@tests.mozilla.org",
version: "2.0",
name: "Test 5",
targetApplications: [{
id: "toolkit@mozilla.org",
minVersion: "1",
maxVersion: "1"
}]
};
var theme1 = { var theme1 = {
id: "theme1@tests.mozilla.org", id: "theme1@tests.mozilla.org",
version: "1.0", version: "1.0",
@ -94,6 +105,9 @@ function run_test() {
dest.append("addon4@tests.mozilla.org"); dest.append("addon4@tests.mozilla.org");
writeInstallRDFToDir(addon4, dest); writeInstallRDFToDir(addon4, dest);
dest = profileDir.clone(); dest = profileDir.clone();
dest.append("addon5@tests.mozilla.org");
writeInstallRDFToDir(addon5, dest);
dest = profileDir.clone();
dest.append("theme1@tests.mozilla.org"); dest.append("theme1@tests.mozilla.org");
writeInstallRDFToDir(theme1, dest); writeInstallRDFToDir(theme1, dest);
dest = profileDir.clone(); dest = profileDir.clone();
@ -111,9 +125,10 @@ function run_test() {
"addon2@tests.mozilla.org", "addon2@tests.mozilla.org",
"addon3@tests.mozilla.org", "addon3@tests.mozilla.org",
"addon4@tests.mozilla.org", "addon4@tests.mozilla.org",
"addon5@tests.mozilla.org",
"theme1@tests.mozilla.org", "theme1@tests.mozilla.org",
"theme2@tests.mozilla.org"], function([a1, a2, "theme2@tests.mozilla.org"], function([a1, a2,
a3, a4, a3, a4, a5,
t1, t2]) { t1, t2]) {
// addon1 was user and app enabled in the old extensions.rdf // addon1 was user and app enabled in the old extensions.rdf
do_check_neq(a1, null); do_check_neq(a1, null);
@ -135,6 +150,12 @@ function run_test() {
do_check_false(a4.userDisabled); do_check_false(a4.userDisabled);
do_check_true(a4.appDisabled); do_check_true(a4.appDisabled);
// addon5 was disabled and compatible but a new version has been installed
// since, it should still be disabled but should be incompatible
do_check_neq(a5, null);
do_check_true(a5.userDisabled);
do_check_true(a5.appDisabled);
// Theme 1 was previously enabled // Theme 1 was previously enabled
do_check_neq(t1, null); do_check_neq(t1, null);
do_check_false(t1.userDisabled); do_check_false(t1.userDisabled);

View File

@ -59,6 +59,17 @@ var addon5 = {
}] }]
}; };
var addon6 = {
id: "addon6@tests.mozilla.org",
version: "2.0",
name: "Test 6",
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "0",
maxVersion: "0"
}]
};
const profileDir = gProfD.clone(); const profileDir = gProfD.clone();
profileDir.append("extensions"); profileDir.append("extensions");
@ -81,6 +92,9 @@ function run_test() {
dest = profileDir.clone(); dest = profileDir.clone();
dest.append("addon5@tests.mozilla.org"); dest.append("addon5@tests.mozilla.org");
writeInstallRDFToDir(addon5, dest); writeInstallRDFToDir(addon5, dest);
dest = profileDir.clone();
dest.append("addon6@tests.mozilla.org");
writeInstallRDFToDir(addon6, dest);
// Write out a minimal database // Write out a minimal database
let dbfile = gProfD.clone(); let dbfile = gProfD.clone();
@ -89,32 +103,43 @@ function run_test() {
getService(AM_Ci.mozIStorageService). getService(AM_Ci.mozIStorageService).
openDatabase(dbfile); openDatabase(dbfile);
db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " + db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"id TEXT, location TEXT, active INTEGER, " + "id TEXT, location TEXT, version TEXT, active INTEGER, " +
"userDisabled INTEGER, installDate INTEGER"); "userDisabled INTEGER, installDate INTEGER");
db.createTable("targetApplication", "addon_internal_id INTEGER, " + db.createTable("targetApplication", "addon_internal_id INTEGER, " +
"id TEXT, minVersion TEXT, maxVersion TEXT"); "id TEXT, minVersion TEXT, maxVersion TEXT");
let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " + let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " +
":active, :userDisabled, :installDate)"); ":version, :active, :userDisabled, :installDate)");
[["addon1@tests.mozilla.org", "app-profile", "1", "0", "0"], let internal_ids = {};
["addon2@tests.mozilla.org", "app-profile", "0", "1", "0"],
["addon3@tests.mozilla.org", "app-profile", "1", "1", "0"], [["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0", "0"],
["addon4@tests.mozilla.org", "app-profile", "0", "0", "0"], ["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "1", "0"],
["addon5@tests.mozilla.org", "app-profile", "1", "0", "0"]].forEach(function(a) { ["addon3@tests.mozilla.org", "app-profile", "2.0", "1", "1", "0"],
["addon4@tests.mozilla.org", "app-profile", "2.0", "0", "0", "0"],
["addon5@tests.mozilla.org", "app-profile", "2.0", "1", "0", "0"],
["addon6@tests.mozilla.org", "app-profile", "1.0", "0", "1", "0"]].forEach(function(a) {
stmt.params.id = a[0]; stmt.params.id = a[0];
stmt.params.location = a[1]; stmt.params.location = a[1];
stmt.params.active = a[2]; stmt.params.version = a[2];
stmt.params.userDisabled = a[3]; stmt.params.active = a[3];
stmt.params.installDate = a[4]; stmt.params.userDisabled = a[4];
stmt.params.installDate = a[5];
stmt.execute(); stmt.execute();
internal_ids[a[0]] = db.lastInsertRowID;
}); });
stmt.finalize(); stmt.finalize();
// Add updated target application into for addon5 // Add updated target application into for addon5
let internal_id = db.lastInsertRowID;
stmt = db.createStatement("INSERT INTO targetApplication VALUES " + stmt = db.createStatement("INSERT INTO targetApplication VALUES " +
"(:internal_id, :id, :minVersion, :maxVersion)"); "(:internal_id, :id, :minVersion, :maxVersion)");
stmt.params.internal_id = internal_id; stmt.params.internal_id = internal_ids["addon5@tests.mozilla.org"];
stmt.params.id = "xpcshell@tests.mozilla.org";
stmt.params.minVersion = "0";
stmt.params.maxVersion = "1";
stmt.execute();
// Add updated target application into for addon6
stmt.params.internal_id = internal_ids["addon6@tests.mozilla.org"];
stmt.params.id = "xpcshell@tests.mozilla.org"; stmt.params.id = "xpcshell@tests.mozilla.org";
stmt.params.minVersion = "0"; stmt.params.minVersion = "0";
stmt.params.maxVersion = "1"; stmt.params.maxVersion = "1";
@ -129,8 +154,9 @@ function run_test() {
"addon2@tests.mozilla.org", "addon2@tests.mozilla.org",
"addon3@tests.mozilla.org", "addon3@tests.mozilla.org",
"addon4@tests.mozilla.org", "addon4@tests.mozilla.org",
"addon5@tests.mozilla.org"], "addon5@tests.mozilla.org",
function([a1, a2, a3, a4, a5]) { "addon6@tests.mozilla.org"],
function([a1, a2, a3, a4, a5, a6]) {
// addon1 was enabled in the database // addon1 was enabled in the database
do_check_neq(a1, null); do_check_neq(a1, null);
do_check_false(a1.userDisabled); do_check_false(a1.userDisabled);
@ -157,5 +183,12 @@ function run_test() {
do_check_false(a5.appDisabled); do_check_false(a5.appDisabled);
do_check_true(a5.isActive); do_check_true(a5.isActive);
do_test_finished(); do_test_finished();
// addon6 was disabled and compatible but a new version has been installed
// since, it should still be disabled but should be incompatible
do_check_neq(a6, null);
do_check_true(a6.userDisabled);
do_check_true(a6.appDisabled);
do_check_false(a6.isActive);
do_test_finished();
}); });
} }