Bug 1772943 - Port osfile.jsm usage to IOUtils in toolkit/mozapps/ r=Gijs,mixedpuppy

Differential Revision: https://phabricator.services.mozilla.com/D148967
This commit is contained in:
Barret Rennie 2022-07-21 04:44:40 +00:00
Родитель 6b159ffeb4
Коммит ccc656a53b
11 изменённых файлов: 72 добавлений и 148 удалений

Просмотреть файл

@ -4,10 +4,6 @@ const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm"
);
const { ProductAddonCheckerTestUtils } = ChromeUtils.import(
"resource://gre/modules/addons/ProductAddonChecker.jsm"
);
AddonTestUtils.initMochitest(this);
const testServer = AddonTestUtils.createHttpServer();
@ -69,9 +65,9 @@ add_task(async function test_management_install() {
},
});
let themeXPIFileHash = await ProductAddonCheckerTestUtils.computeHash(
"sha256",
themeXPIFile.path
let themeXPIFileHash = await IOUtils.computeHexDigest(
themeXPIFile.path,
"sha256"
);
const otherXPIFile = AddonTestUtils.createTempWebExtensionFile({

Просмотреть файл

@ -947,10 +947,7 @@ async function test_checkForAddons_installAddon(
let data = "e~=0.5772156649";
let zipFile = createNewZipFile(zipFileName, data);
let hashFunc = "sha256";
let expectedDigest = await ProductAddonCheckerTestUtils.computeHash(
hashFunc,
zipFile.path
);
let expectedDigest = await IOUtils.computeHexDigest(zipFile.path, hashFunc);
let fileSize = zipFile.fileSize;
if (wantInstallReject) {
fileSize = 1;

Просмотреть файл

@ -27,7 +27,6 @@ const { XPCOMUtils } = ChromeUtils.importESModule(
const { EventEmitter } = ChromeUtils.import(
"resource://gre/modules/EventEmitter.jsm"
);
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const lazy = {};
@ -657,13 +656,14 @@ var AddonTestUtils = {
let loadedData = {};
let fileSuffix = "extensions";
const fileName = `${prefix}-${fileSuffix}.json`;
let jsonStr = await OS.File.read(OS.Path.join(dir.path, fileName), {
encoding: "UTF-8",
}).catch(() => {});
if (jsonStr) {
try {
loadedData[fileSuffix] = await IOUtils.readJSON(
PathUtils.join(dir.path, fileName)
);
this.info(`Loaded ${fileName}`);
loadedData[fileSuffix] = JSON.parse(jsonStr);
}
} catch (e) {}
return this.loadBlocklistRawData(loadedData);
},
@ -933,32 +933,6 @@ var AddonTestUtils = {
this.addonsList = new AddonsList(this.addonStartup);
},
/**
* Recursively create all directories up to and including the given
* path, if they do not exist.
*
* @param {string} path The path of the directory to create.
* @returns {Promise} Resolves when all directories have been created.
*/
recursiveMakeDir(path) {
let paths = [];
for (
let lastPath;
path != lastPath;
lastPath = path, path = OS.Path.dirname(path)
) {
paths.push(path);
}
return Promise.all(
paths
.reverse()
.map(path =>
OS.File.makeDir(path, { ignoreExisting: true }).catch(() => {})
)
);
},
/**
* Writes the given data to a file in the given zip file.
*
@ -1008,7 +982,7 @@ var AddonTestUtils = {
},
async promiseWriteFilesToZip(zip, files, flags) {
await this.recursiveMakeDir(OS.Path.dirname(zip));
await IOUtils.makeDirectory(PathUtils.parent(zip));
this.writeFilesToZip(zip, files, flags);
@ -1016,7 +990,7 @@ var AddonTestUtils = {
},
async promiseWriteFilesToDir(dir, files) {
await this.recursiveMakeDir(dir);
await IOUtils.makeDirectory(dir);
for (let [path, data] of Object.entries(files)) {
path = path.split("/");
@ -1025,21 +999,19 @@ var AddonTestUtils = {
// Create parent directories, if necessary.
let dirPath = dir;
for (let subDir of path) {
dirPath = OS.Path.join(dirPath, subDir);
await OS.File.makeDir(dirPath, { ignoreExisting: true });
dirPath = PathUtils.join(dirPath, subDir);
await PathUtils.makeDirectory(dirPath);
}
const leafPath = PathUtils.join(dirPath, leafName);
if (
typeof data == "object" &&
ChromeUtils.getClassName(data) == "Object"
) {
data = JSON.stringify(data);
await IOUtils.writeJSON(leafPath, data);
} else if (typeof data == "string") {
await IOUtils.writeUTF8(leafPath, data);
}
if (typeof data == "string") {
data = new TextEncoder("utf-8").encode(data);
}
await OS.File.writeAtomic(OS.Path.join(dirPath, leafName), data);
}
return nsFile(dir);
@ -1047,12 +1019,12 @@ var AddonTestUtils = {
promiseWriteFilesToExtension(dir, id, files, unpacked = this.testUnpacked) {
if (unpacked) {
let path = OS.Path.join(dir, id);
let path = PathUtils.join(dir, id);
return this.promiseWriteFilesToDir(path, files);
}
let xpi = OS.Path.join(dir, `${id}.xpi`);
let xpi = PathUtils.join(dir, `${id}.xpi`);
return this.promiseWriteFilesToZip(xpi, files);
},
@ -1268,18 +1240,22 @@ var AddonTestUtils = {
async promiseSetExtensionModifiedTime(path, time) {
await IOUtils.setModificationTime(path, time);
let iterator = new OS.File.DirectoryIterator(path);
const stat = await IOUtils.stat(path);
if (stat.type !== "directory") {
return;
}
const children = await IOUtils.getChildren(path);
try {
await iterator.forEach(entry => {
return this.promiseSetExtensionModifiedTime(entry.path, time);
});
await Promise.all(
children.map(entry => this.promiseSetExtensionModifiedTime(entry, time))
);
} catch (ex) {
if (ex instanceof OS.File.Error) {
if (DOMException.isInstance(ex)) {
return;
}
throw ex;
} finally {
iterator.close().catch(() => {});
}
},
@ -1792,10 +1768,7 @@ var AddonTestUtils = {
this.tempXPIs.push(file);
let manifest = Services.io.newFileURI(file);
await OS.File.writeAtomic(
file.path,
new TextEncoder().encode(JSON.stringify(data))
);
await IOUtils.writeJSON(file.path, data);
this.overrideEntry = lazy.aomStartup.registerChrome(manifest, [
[
"override",

Просмотреть файл

@ -13,7 +13,6 @@ const { Log } = ChromeUtils.import("resource://gre/modules/Log.jsm");
const { CertUtils } = ChromeUtils.import(
"resource://gre/modules/CertUtils.jsm"
);
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const lazy = {};
@ -37,8 +36,6 @@ logger.manageLevelFromPref("extensions.logging.productaddons.level");
* ensure that we fail cleanly in such case.
*/
const TIMEOUT_DELAY_MS = 20000;
// How much of a file to read into memory at a time for hashing
const HASH_CHUNK_SIZE = 8192;
/**
* Gets the status of an XMLHttpRequest either directly or from its underlying
@ -425,13 +422,13 @@ function downloadFile(url, options = { httpsOnlyNoUpgrade: false }) {
return;
}
(async function() {
let f = await OS.File.openUnique(
OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon")
const path = await IOUtils.createUniqueFile(
PathUtils.osTempDir,
"tmpaddon"
);
let path = f.path;
logger.info(`Downloaded file will be saved to ${path}`);
await f.file.close();
await OS.File.writeAtomic(path, new Uint8Array(sr.response));
await IOUtils.write(path, new Uint8Array(sr.response));
return path;
})().then(resolve, reject);
};
@ -467,51 +464,6 @@ function downloadFile(url, options = { httpsOnlyNoUpgrade: false }) {
});
}
/**
* Convert a string containing binary values to hex.
*/
function binaryToHex(input) {
let result = "";
for (let i = 0; i < input.length; ++i) {
let hex = input.charCodeAt(i).toString(16);
if (hex.length == 1) {
hex = "0" + hex;
}
result += hex;
}
return result;
}
/**
* Calculates the hash of a file.
*
* @param hashFunction
* The type of hash function to use, must be supported by nsICryptoHash.
* @param path
* The path of the file to hash.
* @return a promise that resolves to hash of the file or rejects with a JS
* exception in case of error.
*/
var computeHash = async function(hashFunction, path) {
let file = await OS.File.open(path, { existing: true, read: true });
try {
let hasher = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
hasher.initWithString(hashFunction);
let bytes;
do {
bytes = await file.read(HASH_CHUNK_SIZE);
hasher.update(bytes, bytes.length);
} while (bytes.length == HASH_CHUNK_SIZE);
return binaryToHex(hasher.finish(false));
} finally {
await file.close();
}
};
/**
* Verifies that a downloaded file matches what was expected.
*
@ -525,7 +477,7 @@ var computeHash = async function(hashFunction, path) {
*/
var verifyFile = async function(properties, path) {
if (properties.size !== undefined) {
let stat = await OS.File.stat(path);
let stat = await IOUtils.stat(path);
if (stat.size != properties.size) {
throw new Error(
"Downloaded file was " +
@ -539,7 +491,7 @@ var verifyFile = async function(properties, path) {
if (properties.hashFunction !== undefined) {
let expectedDigest = properties.hashValue.toLowerCase();
let digest = await computeHash(properties.hashFunction, path);
let digest = await IOUtils.computeHexDigest(path, properties.hashFunction);
if (digest != expectedDigest) {
throw new Error(
"Hash was `" + digest + "` but expected `" + expectedDigest + "`."
@ -610,7 +562,7 @@ const ProductAddonChecker = {
await verifyFile(addon, path);
return path;
} catch (e) {
await OS.File.remove(path);
await IOUtils.remove(path);
throw e;
}
},
@ -618,8 +570,6 @@ const ProductAddonChecker = {
// For test use only.
const ProductAddonCheckerTestUtils = {
computeHash,
/**
* Used to override ServiceRequest calls with a mock request.
* @param mockRequest The mocked ServiceRequest object.

Просмотреть файл

@ -10,7 +10,14 @@ loadTestSubscript("head_disco.js");
// latest AMO API, by replacing API_RESPONSE_FILE's content with latest AMO API
// response, e.g. from https://addons.allizom.org/api/v4/discovery/?lang=en-US
// The response must contain at least one theme, and one extension.
const API_RESPONSE_FILE = RELATIVE_DIR + "discovery/api_response.json";
const API_RESPONSE_FILE = PathUtils.join(
Services.dirsvc.get("CurWorkD", Ci.nsIFile).path,
// Trim empty component from splitting with trailing slash.
...RELATIVE_DIR.split("/").filter(c => c.length),
"discovery",
"api_response.json"
);
const AMO_TEST_HOST = "rewritten-for-testing.addons.allizom.org";

Просмотреть файл

@ -21,8 +21,6 @@ const {
ExtensionUtils: { promiseEvent, promiseObserved },
} = ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm");
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
AddonTestUtils.initMochitest(this);
// The response to the discovery API, as documented at:
@ -36,7 +34,12 @@ AddonTestUtils.initMochitest(this);
// https://addons.allizom.org/api/v4/discovery/?lang=en-US
//
// The response must contain at least one theme, and one extension.
const DISCOAPI_DEFAULT_FIXTURE = RELATIVE_DIR + "discovery/api_response.json";
const DISCOAPI_DEFAULT_FIXTURE = PathUtils.join(
Services.dirsvc.get("CurWorkD", Ci.nsIFile).path,
...RELATIVE_DIR.split("/"),
"discovery",
"api_response.json"
);
// Read the content of API_RESPONSE_FILE, and replaces any embedded URLs with
// URLs that point to the `amoServer` test server.
@ -44,7 +47,7 @@ async function readAPIResponseFixture(
amoTestHost,
fixtureFilePath = DISCOAPI_DEFAULT_FIXTURE
) {
let apiText = await OS.File.read(fixtureFilePath, { encoding: "utf-8" });
let apiText = await IOUtils.readUTF8(fixtureFilePath);
apiText = apiText.replace(/\bhttps?:\/\/[^"]+(?=")/g, url => {
try {
url = new URL(url);

Просмотреть файл

@ -1,7 +1,6 @@
const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm"
);
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
@ -15,7 +14,7 @@ add_task(async function test_non_ascii_path() {
Ci.nsIEnvironment
);
const PROFILE_VAR = "XPCSHELL_TEST_PROFILE_DIR";
let profileDir = OS.Path.join(
let profileDir = PathUtils.join(
env.get(PROFILE_VAR),
"\u00ce \u00e5m \u00f1\u00f8t \u00e5s\u00e7ii"
);
@ -51,9 +50,8 @@ add_task(async function test_non_ascii_path() {
await AddonTestUtils.promiseInstallFile(xpi2);
await AddonTestUtils.promiseShutdownManager();
let dbfile = OS.Path.join(profileDir, "extensions.json");
let raw = new TextDecoder().decode(await OS.File.read(dbfile));
let data = JSON.parse(raw);
let dbfile = PathUtils.join(profileDir, "extensions.json");
let data = await IOUtils.readJSON(dbfile);
let addons = data.addons.filter(a => a.id !== DEFAULT_THEME_ID);
Assert.ok(Array.isArray(addons), "extensions.json has addons array");

Просмотреть файл

@ -36,7 +36,7 @@ const ID1 = "addon1@tests.mozilla.org";
const ID2 = "addon2@tests.mozilla.org";
const ID3 = "addon3@tests.mozilla.org";
const ID4 = "addon4@tests.mozilla.org";
const PATH4 = OS.Path.join(globalDir.path, `${ID4}.xpi`);
const PATH4 = PathUtils.join(globalDir.path, `${ID4}.xpi`);
add_task(async function setup() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");

Просмотреть файл

@ -34,7 +34,7 @@ add_task(async function test_upgrade_incompatible() {
});
// swap the incompatible extension in for the original
let path = OS.Path.join(gProfD.path, "extensions", `${ID}.xpi`);
let path = PathUtils.join(gProfD.path, "extensions", `${ID}.xpi`);
let fileInfo = await IOUtils.stat(path);
let timestamp = fileInfo.lastModified;

Просмотреть файл

@ -1,4 +1,3 @@
let { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
let { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const RELATIVE_PATH = "browser/toolkit/mozapps/extensions/test/xpinstall";
@ -50,7 +49,7 @@ function handleRequest(aRequest, aResponse) {
LOG("Completing download");
try {
// Doesn't seem to be a sane way to read using OS.File and write to an
// Doesn't seem to be a sane way to read using IOUtils and write to an
// nsIOutputStream so here we are.
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(xpiFile);
@ -79,17 +78,16 @@ function handleRequest(aRequest, aResponse) {
aResponse.processAsync();
OS.File.getCurrentDirectory().then(dir => {
xpiFile = OS.Path.join(dir, ...RELATIVE_PATH.split("/"), params.file);
LOG("Starting slow download of " + xpiFile);
const dir = Services.dirsvc.get("CurWorkD", Ci.nsIFile).path;
xpiFile = PathUtils.join(dir, ...RELATIVE_PATH.split("/"), params.file);
LOG("Starting slow download of " + xpiFile);
OS.File.stat(xpiFile).then(info => {
aResponse.setHeader("Content-Type", "binary/octet-stream");
aResponse.setHeader("Content-Length", info.size.toString());
IOUtils.stat(xpiFile).then(info => {
aResponse.setHeader("Content-Type", "binary/octet-stream");
aResponse.setHeader("Content-Length", info.size.toString());
LOG("Download paused");
waitForComplete.then(complete_download);
});
LOG("Download paused");
waitForComplete.then(complete_download);
});
} else if (params.continue) {
dump(

Просмотреть файл

@ -18,6 +18,8 @@ module.exports = {
ContentTask: false,
ContentTaskUtils: false,
EventUtils: false,
IOUtils: false,
PathUtils: false,
PromiseDebugging: false,
SpecialPowers: false,
TestUtils: false,