зеркало из https://github.com/mozilla/gecko-dev.git
Bug 555083: Add support for registry install locations. r=robstrong
This commit is contained in:
Родитель
b81f3abe6a
Коммит
ddc0c3c62c
|
@ -782,22 +782,53 @@ var XPIProvider = {
|
|||
this.installLocations = [];
|
||||
this.installLocationsByName = {};
|
||||
|
||||
// These must be in order of priority for processFileChanges etc. to work
|
||||
[
|
||||
[KEY_APP_GLOBAL, KEY_APPDIR, [DIR_EXTENSIONS], true],
|
||||
[KEY_APP_SYSTEM_LOCAL, "XRESysLExtPD", [Services.appinfo.ID], true],
|
||||
[KEY_APP_SYSTEM_SHARE, "XRESysSExtPD", [Services.appinfo.ID], true],
|
||||
[KEY_APP_SYSTEM_USER, "XREUSysExt", [Services.appinfo.ID], true],
|
||||
[KEY_APP_PROFILE, KEY_PROFILEDIR, [DIR_EXTENSIONS], false]
|
||||
].forEach(function([name, key, paths, locked]) {
|
||||
function addDirectoryInstallLocation(name, key, paths, locked) {
|
||||
try {
|
||||
let dir = FileUtils.getDir(key, paths);
|
||||
let location = new DirectoryInstallLocation(name, dir, locked);
|
||||
this.installLocations.push(location);
|
||||
this.installLocationsByName[location.name] = location;
|
||||
var dir = FileUtils.getDir(key, paths);
|
||||
}
|
||||
catch (e) { }
|
||||
}, this);
|
||||
catch (e) {
|
||||
// Some directories aren't defined on some platforms, ignore them
|
||||
LOG("Skipping unavailable install location " + name);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var location = new DirectoryInstallLocation(name, dir, locked);
|
||||
}
|
||||
catch (e) {
|
||||
WARN("Failed to add directory install location " + name + " " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
XPIProvider.installLocations.push(location);
|
||||
XPIProvider.installLocationsByName[location.name] = location;
|
||||
}
|
||||
|
||||
function addRegistryInstallLocation(name, rootkey) {
|
||||
try {
|
||||
var location = new WinRegInstallLocation(name, rootkey);
|
||||
}
|
||||
catch (e) {
|
||||
WARN("Failed to add registry install location " + name + " " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
XPIProvider.installLocations.push(location);
|
||||
XPIProvider.installLocationsByName[location.name] = location;
|
||||
}
|
||||
|
||||
let hasRegistry = ("nsIWindowsRegKey" in Ci);
|
||||
|
||||
// These must be in order of priority for processFileChanges etc. to work
|
||||
if (hasRegistry)
|
||||
addRegistryInstallLocation("winreg-app-global", Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE);
|
||||
addDirectoryInstallLocation(KEY_APP_SYSTEM_LOCAL, "XRESysLExtPD", [Services.appinfo.ID], true);
|
||||
addDirectoryInstallLocation(KEY_APP_SYSTEM_SHARE, "XRESysSExtPD", [Services.appinfo.ID], true);
|
||||
addDirectoryInstallLocation(KEY_APP_GLOBAL, KEY_APPDIR, [DIR_EXTENSIONS], true);
|
||||
if (hasRegistry)
|
||||
addRegistryInstallLocation("winreg-app-user", Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER);
|
||||
addDirectoryInstallLocation(KEY_APP_SYSTEM_USER, "XREUSysExt", [Services.appinfo.ID], true);
|
||||
addDirectoryInstallLocation(KEY_APP_PROFILE, KEY_PROFILEDIR, [DIR_EXTENSIONS], false);
|
||||
|
||||
this.defaultSkin = Prefs.getDefaultCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN,
|
||||
"classic/1.0");
|
||||
|
@ -1092,7 +1123,10 @@ var XPIProvider = {
|
|||
catch (e) {
|
||||
WARN("Add-on is invalid: " + e);
|
||||
XPIDatabase.removeAddonMetadata(oldAddon);
|
||||
installLocation.uninstallAddon(oldAddon.id);
|
||||
if (!installLocation.locked)
|
||||
installLocation.uninstallAddon(oldAddon.id);
|
||||
else
|
||||
WARN("Could not uninstall invalid item from locked install location");
|
||||
// If this was an active add-on then we must force a restart
|
||||
if (oldAddon.active) {
|
||||
if (oldAddon.type == "bootstrapped")
|
||||
|
@ -1277,9 +1311,12 @@ var XPIProvider = {
|
|||
catch (e) {
|
||||
WARN("Add-on is invalid: " + e);
|
||||
|
||||
// Remove the invalid add-on from the install location, no restart will
|
||||
// be necessary
|
||||
installLocation.uninstallAddon(id);
|
||||
// Remove the invalid add-on from the install location if the install
|
||||
// location isn't locked, no restart will be necessary
|
||||
if (!installLocation.locked)
|
||||
installLocation.uninstallAddon(id);
|
||||
else
|
||||
WARN("Could not uninstall invalid item from locked install location");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4582,11 +4619,13 @@ function WinRegInstallLocation(name, rootKey) {
|
|||
// cases, we just leave ourselves in the empty state.
|
||||
try {
|
||||
key.open(this._rootKey, path, Ci.nsIWindowsRegKey.ACCESS_READ);
|
||||
this._readAddons(key);
|
||||
}
|
||||
catch (e) { }
|
||||
if (key)
|
||||
key.close();
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readAddons(key);
|
||||
key.close();
|
||||
}
|
||||
|
||||
WinRegInstallLocation.prototype = {
|
||||
|
@ -4635,6 +4674,9 @@ WinRegInstallLocation.prototype = {
|
|||
this._IDToDirMap[id] = dir;
|
||||
this._DirToIDMap[dir.path] = id;
|
||||
}
|
||||
else {
|
||||
WARN("Ignoring missing add-on in " + dir.path);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ function createAppInfo(id, name, version, platformVersion) {
|
|||
AM_Ci.nsICrashReporter,
|
||||
AM_Ci.nsISupports])
|
||||
};
|
||||
|
||||
|
||||
var XULAppInfoFactory = {
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer != null)
|
||||
|
@ -528,6 +528,116 @@ function ensure_test_completed() {
|
|||
if (gExpectedInstalls)
|
||||
do_check_eq(gExpectedInstalls.length, 0);
|
||||
}
|
||||
|
||||
if ("nsIWindowsRegKey" in AM_Ci) {
|
||||
var MockRegistry = {
|
||||
LOCAL_MACHINE: {},
|
||||
CURRENT_USER: {},
|
||||
|
||||
setValue: function(root, path, name, value) {
|
||||
switch (root) {
|
||||
case AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE:
|
||||
var rootKey = MockRegistry.LOCAL_MACHINE;
|
||||
break
|
||||
case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER:
|
||||
rootKey = MockRegistry.CURRENT_USER;
|
||||
break
|
||||
}
|
||||
|
||||
if (!(path in rootKey)) {
|
||||
rootKey[path] = [];
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < rootKey[path].length; i++) {
|
||||
if (rootKey[path][i].name == name) {
|
||||
if (value === null)
|
||||
rootKey[path].splice(i, 1);
|
||||
else
|
||||
rootKey[path][i].value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value === null)
|
||||
return;
|
||||
|
||||
rootKey[path].push({
|
||||
name: name,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a mock nsIWindowsRegistry implementation. It only implements the
|
||||
* methods that the extension manager requires.
|
||||
*/
|
||||
function MockWindowsRegKey() {
|
||||
}
|
||||
|
||||
MockWindowsRegKey.prototype = {
|
||||
values: null,
|
||||
|
||||
// --- Overridden nsISupports interface functions ---
|
||||
QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIWindowsRegKey]),
|
||||
|
||||
// --- Overridden nsIWindowsRegKey interface functions ---
|
||||
open: function(aRootKey, aRelPath, aMode) {
|
||||
switch (aRootKey) {
|
||||
case AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE:
|
||||
var rootKey = MockRegistry.LOCAL_MACHINE;
|
||||
break
|
||||
case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER:
|
||||
rootKey = MockRegistry.CURRENT_USER;
|
||||
break
|
||||
}
|
||||
|
||||
if (!(aRelPath in rootKey))
|
||||
rootKey[aRelPath] = [];
|
||||
this.values = rootKey[aRelPath];
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.values = null;
|
||||
},
|
||||
|
||||
get valueCount() {
|
||||
if (!this.values)
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
return this.values.length;
|
||||
},
|
||||
|
||||
getValueName: function(aIndex) {
|
||||
if (!this.values || aIndex >= this.values.length)
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
return this.values[aIndex].name;
|
||||
},
|
||||
|
||||
readStringValue: function(aName) {
|
||||
for (let i = 0; i < this.values.length; i++) {
|
||||
if (this.values[i].name == aName)
|
||||
return this.values[i].value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var WinRegFactory = {
|
||||
createInstance: function(aOuter, aIid) {
|
||||
if (aOuter != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
var key = new MockWindowsRegKey();
|
||||
return key.QueryInterface(aIid);
|
||||
}
|
||||
};
|
||||
|
||||
var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(Components.ID("{0478de5b-0f38-4edb-851d-4c99f1ed8eba}"),
|
||||
"Mock Windows Registry Implementation",
|
||||
"@mozilla.org/windows-registry-key;1", WinRegFactory);
|
||||
}
|
||||
|
||||
// Get the profile directory for tests to use.
|
||||
const gProfD = do_get_profile().QueryInterface(AM_Ci.nsILocalFile);
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that extensions installed through the registry work as expected
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
|
||||
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 2",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "2"
|
||||
}]
|
||||
};
|
||||
|
||||
const addon1Dir = gProfD.clone();
|
||||
addon1Dir.append("addon1");
|
||||
writeInstallRDFToDir(addon1, addon1Dir);
|
||||
const addon2Dir = gProfD.clone();
|
||||
addon2Dir.append("addon2");
|
||||
writeInstallRDFToDir(addon2, addon2Dir);
|
||||
|
||||
function run_test() {
|
||||
// This test only works where there is a registry.
|
||||
if (!("nsIWindowsRegKey" in AM_Ci))
|
||||
return;
|
||||
|
||||
do_test_pending();
|
||||
|
||||
run_test_1();
|
||||
}
|
||||
|
||||
// Tests whether basic registry install works
|
||||
function run_test_1() {
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", addon1Dir.path);
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon2@tests.mozilla.org", addon2Dir.path);
|
||||
|
||||
startupManager(1);
|
||||
|
||||
AddonManager.getAddons(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org"], function([a1, a2]) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_true(a1.isActive);
|
||||
do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL));
|
||||
do_check_neq(a2, null);
|
||||
do_check_true(a2.isActive);
|
||||
do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL));
|
||||
|
||||
run_test_2();
|
||||
});
|
||||
}
|
||||
|
||||
// Tests whether uninstalling from the registry works
|
||||
function run_test_2() {
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", null);
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon2@tests.mozilla.org", null);
|
||||
|
||||
restartManager(1);
|
||||
|
||||
AddonManager.getAddons(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org"], function([a1, a2]) {
|
||||
do_check_eq(a1, null);
|
||||
do_check_eq(a2, null);
|
||||
|
||||
run_test_3();
|
||||
});
|
||||
}
|
||||
|
||||
// Checks that the ID in the registry must match that in the install manifest
|
||||
function run_test_3() {
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", addon2Dir.path);
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon2@tests.mozilla.org", addon1Dir.path);
|
||||
|
||||
restartManager(0);
|
||||
|
||||
AddonManager.getAddons(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org"], function([a1, a2]) {
|
||||
do_check_eq(a1, null);
|
||||
do_check_eq(a2, null);
|
||||
|
||||
// Restarting with bad items in the registry should not force an EM restart
|
||||
restartManager(0);
|
||||
|
||||
run_test_4();
|
||||
});
|
||||
}
|
||||
|
||||
// Tests whether an extension's ID can change without its directory changing
|
||||
function run_test_4() {
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", null);
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon2@tests.mozilla.org", null);
|
||||
|
||||
restartManager(0);
|
||||
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", addon1Dir.path);
|
||||
restartManager(1);
|
||||
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon1@tests.mozilla.org", null);
|
||||
MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Mozilla\\XPCShell\\Extensions",
|
||||
"addon2@tests.mozilla.org", addon1Dir.path);
|
||||
writeInstallRDFToDir(addon2, addon1Dir);
|
||||
|
||||
restartManager(1);
|
||||
|
||||
AddonManager.getAddons(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org"], function([a1, a2]) {
|
||||
do_check_eq(a1, null);
|
||||
do_check_neq(a2, null);
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
|
@ -120,6 +120,9 @@ function run_test_1() {
|
|||
dest = profileDir.clone();
|
||||
dest.append("addon2@tests.mozilla.org");
|
||||
writeInstallRDFToDir(addon2, dest);
|
||||
// Attempt to make this look like it was added some time in the past so
|
||||
// the change in run_test_2 makes the last modified time change.
|
||||
dest.lastModifiedTime -= 5000;
|
||||
dest = profileDir.clone();
|
||||
dest.append("addon3@tests.mozilla.org");
|
||||
writeInstallRDFToDir(addon3, dest);
|
||||
|
|
Загрузка…
Ссылка в новой задаче