mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
Bug 617289: PluginProvider doesn't keep IDs of plugins consistent between restarts. r=robstrong
This commit is contained in:
parent
acc6ecc70e
commit
0e53288b95
@ -54,10 +54,41 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
});
|
||||
}, this);
|
||||
|
||||
function getIDHashForString(aStr) {
|
||||
// return the two-digit hexadecimal code for a byte
|
||||
function toHexString(charCode)
|
||||
("0" + charCode.toString(16)).slice(-2);
|
||||
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(Ci.nsICryptoHash.MD5);
|
||||
let stringStream = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsIStringInputStream);
|
||||
stringStream.data = aStr ? aStr : "null";
|
||||
hasher.updateFromStream(stringStream, -1);
|
||||
|
||||
// convert the binary hash data to a hex string.
|
||||
let binary = hasher.finish(false);
|
||||
let hash = [toHexString(binary.charCodeAt(i)) for (i in binary)].join("").toLowerCase();
|
||||
return "{" + hash.substr(0, 8) + "-" +
|
||||
hash.substr(8, 4) + "-" +
|
||||
hash.substr(12, 4) + "-" +
|
||||
hash.substr(16, 4) + "-" +
|
||||
hash.substr(20) + "}";
|
||||
}
|
||||
|
||||
var PluginProvider = {
|
||||
// A dictionary mapping IDs to names and descriptions
|
||||
plugins: null,
|
||||
|
||||
/**
|
||||
* Called when the application is shutting down. Only necessary for tests
|
||||
* to be able to simulate a shutdown.
|
||||
*/
|
||||
shutdown: function PL_shutdown() {
|
||||
this.plugins = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to get an Addon with a particular ID.
|
||||
*
|
||||
@ -73,17 +104,9 @@ var PluginProvider = {
|
||||
if (aId in this.plugins) {
|
||||
let name = this.plugins[aId].name;
|
||||
let description = this.plugins[aId].description;
|
||||
let tags = this.plugins[aId].tags;
|
||||
|
||||
let tags = Cc["@mozilla.org/plugin/host;1"].
|
||||
getService(Ci.nsIPluginHost).
|
||||
getPluginTags({});
|
||||
let selected = [];
|
||||
tags.forEach(function(aTag) {
|
||||
if (aTag.name == name && aTag.description == description)
|
||||
selected.push(aTag);
|
||||
}, this);
|
||||
|
||||
aCallback(new PluginWrapper(aId, name, description, selected));
|
||||
aCallback(new PluginWrapper(aId, name, description, tags));
|
||||
}
|
||||
else {
|
||||
aCallback(null);
|
||||
@ -148,19 +171,24 @@ var PluginProvider = {
|
||||
getPluginTags({});
|
||||
|
||||
this.plugins = {};
|
||||
let seen = {};
|
||||
let plugins = {};
|
||||
tags.forEach(function(aTag) {
|
||||
if (!(aTag.name in seen))
|
||||
seen[aTag.name] = {};
|
||||
if (!(aTag.description in seen[aTag.name])) {
|
||||
let id = Cc["@mozilla.org/uuid-generator;1"].
|
||||
getService(Ci.nsIUUIDGenerator).
|
||||
generateUUID();
|
||||
this.plugins[id] = {
|
||||
if (!(aTag.name in plugins))
|
||||
plugins[aTag.name] = {};
|
||||
if (!(aTag.description in plugins[aTag.name])) {
|
||||
let plugin = {
|
||||
name: aTag.name,
|
||||
description: aTag.description
|
||||
description: aTag.description,
|
||||
tags: [aTag]
|
||||
};
|
||||
seen[aTag.name][aTag.description] = true;
|
||||
|
||||
let id = getIDHashForString(aTag.name + aTag.description);
|
||||
|
||||
plugins[aTag.name][aTag.description] = plugin;
|
||||
this.plugins[id] = plugin;
|
||||
}
|
||||
else {
|
||||
plugins[aTag.name][aTag.description].tags.push(aTag);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
@ -0,0 +1,175 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// This verifies that duplicate plugins are coalesced and maintain their ID
|
||||
// across restarts.
|
||||
|
||||
var PLUGINS = [{
|
||||
name: "Duplicate Plugin 1",
|
||||
description: "A duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "/home/mozilla/.plugins/dupplugin1.so"
|
||||
}, {
|
||||
name: "Duplicate Plugin 1",
|
||||
description: "A duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "",
|
||||
filename: "/usr/lib/plugins/dupplugin1.so"
|
||||
}, {
|
||||
name: "Duplicate Plugin 2",
|
||||
description: "Another duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "/home/mozilla/.plugins/dupplugin2.so"
|
||||
}, {
|
||||
name: "Duplicate Plugin 2",
|
||||
description: "Another duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "",
|
||||
filename: "/usr/lib/plugins/dupplugin2.so"
|
||||
}, {
|
||||
name: "Non-duplicate Plugin", // 3
|
||||
description: "Not a duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "/home/mozilla/.plugins/dupplugin3.so"
|
||||
}, {
|
||||
name: "Non-duplicate Plugin", // 4
|
||||
description: "Not a duplicate because the descriptions are different",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "",
|
||||
filename: "/usr/lib/plugins/dupplugin4.so"
|
||||
}, {
|
||||
name: "Another Non-duplicate Plugin", // 5
|
||||
description: "Not a duplicate plugin",
|
||||
version: "1",
|
||||
blocklisted: false,
|
||||
disabled: false,
|
||||
filename: "/home/mozilla/.plugins/dupplugin5.so"
|
||||
}];
|
||||
|
||||
// A fake plugin host to return the plugins defined above
|
||||
var PluginHost = {
|
||||
getPluginTags: function(countRef) {
|
||||
countRef.value = PLUGINS.length;
|
||||
return PLUGINS;
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsIPluginHost)
|
||||
|| iid.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
var PluginHostFactory = {
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return PluginHost.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"),
|
||||
"Fake Plugin Host",
|
||||
"@mozilla.org/plugin/host;1", PluginHostFactory);
|
||||
|
||||
var gPluginIDs = [null, null, null, null, null];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
|
||||
startupManager();
|
||||
|
||||
run_test_1();
|
||||
}
|
||||
|
||||
function found_plugin(aNum, aId) {
|
||||
if (gPluginIDs[aNum])
|
||||
do_throw("Found duplicate of plugin " + aNum);
|
||||
gPluginIDs[aNum] = aId;
|
||||
}
|
||||
|
||||
// Test that the plugins were coalesced and all appear in the returned list
|
||||
function run_test_1() {
|
||||
AddonManager.getAddonsByTypes(["plugin"], function(aAddons) {
|
||||
do_check_eq(aAddons.length, 5);
|
||||
aAddons.forEach(function(aAddon) {
|
||||
if (aAddon.name == "Duplicate Plugin 1") {
|
||||
found_plugin(0, aAddon.id);
|
||||
do_check_eq(aAddon.description, "A duplicate plugin");
|
||||
}
|
||||
else if (aAddon.name == "Duplicate Plugin 2") {
|
||||
found_plugin(1, aAddon.id);
|
||||
do_check_eq(aAddon.description, "Another duplicate plugin");
|
||||
}
|
||||
else if (aAddon.name == "Another Non-duplicate Plugin") {
|
||||
found_plugin(5, aAddon.id);
|
||||
do_check_eq(aAddon.description, "Not a duplicate plugin");
|
||||
}
|
||||
else if (aAddon.name == "Non-duplicate Plugin") {
|
||||
if (aAddon.description == "Not a duplicate plugin")
|
||||
found_plugin(3, aAddon.id);
|
||||
else if (aAddon.description == "Not a duplicate because the descriptions are different")
|
||||
found_plugin(4, aAddon.id);
|
||||
else
|
||||
do_throw("Found unexpected plugin with description " + aAddon.description);
|
||||
}
|
||||
else {
|
||||
do_throw("Found unexpected plugin " + aAddon.name);
|
||||
}
|
||||
});
|
||||
|
||||
run_test_2();
|
||||
});
|
||||
}
|
||||
|
||||
// Test that disabling a coalesced plugin disables all its tags
|
||||
function run_test_2() {
|
||||
AddonManager.getAddonByID(gPluginIDs[0], function(p) {
|
||||
do_check_false(p.userDisabled);
|
||||
p.userDisabled = true;
|
||||
do_check_true(PLUGINS[0].disabled);
|
||||
do_check_true(PLUGINS[1].disabled);
|
||||
|
||||
run_test_3();
|
||||
});
|
||||
}
|
||||
|
||||
// Test that IDs persist across restart
|
||||
function run_test_3() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID(gPluginIDs[0], function(p) {
|
||||
do_check_neq(p, null);
|
||||
do_check_eq(p.name, "Duplicate Plugin 1");
|
||||
do_check_eq(p.description, "A duplicate plugin");
|
||||
|
||||
// Reorder the plugins and restart again
|
||||
[PLUGINS[0], PLUGINS[1]] = [PLUGINS[1], PLUGINS[0]];
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID(gPluginIDs[0], function(p) {
|
||||
do_check_neq(p, null);
|
||||
do_check_eq(p.name, "Duplicate Plugin 1");
|
||||
do_check_eq(p.description, "A duplicate plugin");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
});
|
||||
}
|
@ -166,6 +166,18 @@ function run_test_3(p) {
|
||||
do_check_true(p.isActive);
|
||||
do_check_eq(p.name, "Test Plug-in");
|
||||
|
||||
run_test_4();
|
||||
});
|
||||
}
|
||||
|
||||
// Verify that after a restart the test plugin has the same ID
|
||||
function run_test_4() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID(gID, function(p) {
|
||||
do_check_neq(p, null);
|
||||
do_check_eq(p.name, "Test Plug-in");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user