The existing code for the `browser_aboutthirdparty.js` test attempts to load a DLL indirectly by means of a Rube Goldberg process involving a directly-instantiated file-picker. This appears to be the source of the severe flakiness of this test. This approach was reasonable when the file-picker was the primary source of deleterious third-party DLLs; but now that we generally open file- pickers out-of-process, there isn't as much of a reason to test that particular injection mechanism. Let's just load the test DLL directly, instead. This patch has two caveats: * The test fails _consistently_, rather than flakily, on ASAN builds. The reason for that remains to be investigated, but probably belongs in a separate bug; for now, we simply leave it disabled. * The test expects the DLL to be a shell extension, and fails with complaints if it's not. There's no other reason to have any of the shell-extension-registration machinery in there, though, so it can (and probably should) be removed, and the test rewritten accordingly. In the interests of swiftly deflaking it, though, this is also being left for a separate bug. Outside of test-only code, no functional changes. Differential Revision: https://phabricator.services.mozilla.com/D231462
140 lines
3.9 KiB
JavaScript
140 lines
3.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
const kClsidTestShellEx = "{10a9521e-0205-4cc7-93a1-62f30a9a54b3}";
|
|
const kFriendlyName = "Minimum Shell Extension for Firefox testing";
|
|
const kExtensionSubkeys = [".zzz\\shellex\\IconHandler"];
|
|
const kExtensionModuleName = "TestShellEx.dll";
|
|
const kUserBlockedModuleName = "TestDllBlocklist_UserBlocked.dll";
|
|
const kFileFilterInDialog = "*.zzz";
|
|
const kATP = Cc["@mozilla.org/about-thirdparty;1"].getService(
|
|
Ci.nsIAboutThirdParty
|
|
);
|
|
|
|
function loadShellExtension() {
|
|
// This method call attempts to load TestShellEx.dll directly. (We no longer
|
|
// attempt to load it indirectly via the Windows file dialog.)
|
|
kATP.loadModuleForTesting(getTestFilePath(kExtensionModuleName));
|
|
}
|
|
|
|
async function registerObject() {
|
|
const reg = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
|
Ci.nsIWindowsRegKey
|
|
);
|
|
|
|
reg.create(
|
|
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
|
"Software\\Classes\\CLSID\\" + kClsidTestShellEx,
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
|
|
reg.writeStringValue("", kFriendlyName);
|
|
|
|
const inprocServer = reg.createChild(
|
|
"InprocServer32",
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
|
|
const moduleFullPath = getTestFilePath(kExtensionModuleName);
|
|
Assert.ok(await IOUtils.exists(moduleFullPath), "The module file exists.");
|
|
|
|
inprocServer.writeStringValue("", moduleFullPath);
|
|
inprocServer.writeStringValue("ThreadingModel", "Apartment");
|
|
reg.close();
|
|
|
|
info("registerObject() done - " + moduleFullPath);
|
|
}
|
|
|
|
function registerExtensions() {
|
|
for (const subkey of kExtensionSubkeys) {
|
|
const reg = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
|
Ci.nsIWindowsRegKey
|
|
);
|
|
reg.create(
|
|
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
|
"Software\\Classes\\" + subkey,
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
|
|
let currentExtension = "";
|
|
try {
|
|
// If the key was just created above, the default value does not exist,
|
|
// so readStringValue will throw NS_ERROR_FAILURE.
|
|
currentExtension = reg.readStringValue("");
|
|
} catch (e) {}
|
|
|
|
try {
|
|
if (!currentExtension) {
|
|
reg.writeStringValue("", kClsidTestShellEx);
|
|
} else if (currentExtension != kClsidTestShellEx) {
|
|
throw new Error(
|
|
`Another extension \`${currentExtension}\` has been registered.`
|
|
);
|
|
}
|
|
} catch (e) {
|
|
throw new Error("Failed to register TestShellEx.dll: " + e);
|
|
} finally {
|
|
reg.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
function unregisterAll() {
|
|
for (const subkey of kExtensionSubkeys) {
|
|
const reg = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
|
Ci.nsIWindowsRegKey
|
|
);
|
|
|
|
try {
|
|
reg.open(
|
|
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
|
"Software\\Classes\\" + subkey,
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
|
|
if (reg.readStringValue("") != kClsidTestShellEx) {
|
|
// If another extension is registered, don't overwrite it.
|
|
continue;
|
|
}
|
|
|
|
// Set an empty string instead of deleting the key
|
|
// not to touch non-default values.
|
|
reg.writeStringValue("", "");
|
|
} catch (e) {
|
|
info(`Failed to unregister \`${subkey}\`: ` + e);
|
|
} finally {
|
|
reg.close();
|
|
}
|
|
}
|
|
|
|
const reg = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
|
Ci.nsIWindowsRegKey
|
|
);
|
|
reg.open(
|
|
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
|
"Software\\Classes\\CLSID",
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
|
|
try {
|
|
const child = reg.openChild(
|
|
kClsidTestShellEx,
|
|
Ci.nsIWindowsRegKey.ACCESS_ALL
|
|
);
|
|
try {
|
|
child.removeChild("InprocServer32");
|
|
} catch (e) {
|
|
} finally {
|
|
child.close();
|
|
}
|
|
|
|
reg.removeChild(kClsidTestShellEx);
|
|
} catch (e) {
|
|
} finally {
|
|
reg.close();
|
|
}
|
|
}
|