mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 1746667 - Make PathUtils path lookups sync on main thread r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D137217
This commit is contained in:
parent
c1424ed185
commit
f7c7ff7d55
@ -99,22 +99,37 @@ namespace PathUtils {
|
||||
* @return Whether or not the path is absolute.
|
||||
*/
|
||||
boolean isAbsolute(DOMString path);
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
partial namespace PathUtils {
|
||||
[Throws, BinaryName="ProfileDirSync"]
|
||||
readonly attribute DOMString profileDir;
|
||||
|
||||
[Throws, BinaryName="LocalProfileDirSync"]
|
||||
readonly attribute DOMString localProfileDir;
|
||||
|
||||
[Throws, BinaryName="TempDirSync"]
|
||||
readonly attribute DOMString tempDir;
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker)]
|
||||
partial namespace PathUtils {
|
||||
/**
|
||||
* The profile directory.
|
||||
*/
|
||||
[Throws]
|
||||
[Throws, BinaryName="GetProfileDirAsync"]
|
||||
Promise<DOMString> getProfileDir();
|
||||
|
||||
/**
|
||||
* The local-specific profile directory.
|
||||
*/
|
||||
[Throws]
|
||||
[Throws, BinaryName="GetProfileDirAsync"]
|
||||
Promise<DOMString> getLocalProfileDir();
|
||||
|
||||
/**
|
||||
* The temporary directory for the process.
|
||||
*/
|
||||
[Throws]
|
||||
[Throws, BinaryName="GetTempDirAsync"]
|
||||
Promise<DOMString> getTempDir();
|
||||
};
|
||||
|
@ -39,6 +39,8 @@ static constexpr auto ERROR_INITIALIZE_PATH = "Could not initialize path"_ns;
|
||||
static constexpr auto ERROR_GET_PARENT = "Could not get parent path"_ns;
|
||||
static constexpr auto ERROR_JOIN = "Could not append to path"_ns;
|
||||
|
||||
static constexpr auto COLON = ": "_ns;
|
||||
|
||||
static void ThrowError(ErrorResult& aErr, const nsresult aResult,
|
||||
const nsCString& aMessage) {
|
||||
nsAutoCStringN<32> errName;
|
||||
@ -46,7 +48,7 @@ static void ThrowError(ErrorResult& aErr, const nsresult aResult,
|
||||
|
||||
nsAutoCStringN<256> formattedMsg;
|
||||
formattedMsg.Append(aMessage);
|
||||
formattedMsg.Append(": "_ns);
|
||||
formattedMsg.Append(COLON);
|
||||
formattedMsg.Append(errName);
|
||||
|
||||
switch (aResult) {
|
||||
@ -347,25 +349,57 @@ bool PathUtils::IsAbsolute(const GlobalObject&, const nsAString& aPath) {
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::GetProfileDir(const GlobalObject& aGlobal,
|
||||
ErrorResult& aErr) {
|
||||
void PathUtils::GetProfileDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
return DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectory(aGlobal, aErr, DirectoryCache::Directory::Profile);
|
||||
DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectorySync(aResult, aErr, DirectoryCache::Directory::Profile);
|
||||
}
|
||||
void PathUtils::GetLocalProfileDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectorySync(aResult, aErr, DirectoryCache::Directory::LocalProfile);
|
||||
}
|
||||
void PathUtils::GetTempDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectorySync(aResult, aErr, DirectoryCache::Directory::Temp);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::GetLocalProfileDir(
|
||||
already_AddRefed<Promise> PathUtils::GetProfileDirAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr) {
|
||||
// NB: This will eventually be off-main-thread only.
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
return DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectory(aGlobal, aErr, DirectoryCache::Directory::LocalProfile);
|
||||
.GetDirectoryAsync(aGlobal, aErr, DirectoryCache::Directory::Profile);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::GetTempDir(const GlobalObject& aGlobal,
|
||||
ErrorResult& aErr) {
|
||||
already_AddRefed<Promise> PathUtils::GetLocalProfileDirAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr) {
|
||||
// NB: This will eventually be off-main-thread only.
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
return DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectory(aGlobal, aErr, DirectoryCache::Directory::Temp);
|
||||
.GetDirectoryAsync(aGlobal, aErr,
|
||||
DirectoryCache::Directory::LocalProfile);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::GetTempDirAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr) {
|
||||
// NB: This will eventually be off-main-thread only.
|
||||
|
||||
auto guard = sDirCache.Lock();
|
||||
return DirectoryCache::Ensure(guard.ref())
|
||||
.GetDirectoryAsync(aGlobal, aErr, DirectoryCache::Directory::Temp);
|
||||
}
|
||||
|
||||
PathUtils::DirectoryCache::DirectoryCache() {
|
||||
@ -397,7 +431,28 @@ PathUtils::DirectoryCache& PathUtils::DirectoryCache::Ensure(
|
||||
return aCache.ref();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::DirectoryCache::GetDirectory(
|
||||
void PathUtils::DirectoryCache::GetDirectorySync(
|
||||
nsString& aResult, ErrorResult& aErr, const Directory aRequestedDir) {
|
||||
MOZ_RELEASE_ASSERT(aRequestedDir < Directory::Count);
|
||||
|
||||
if (nsresult rv = PopulateDirectoriesImpl(aRequestedDir); NS_FAILED(rv)) {
|
||||
nsAutoCStringN<32> errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
|
||||
nsAutoCStringN<256> msg;
|
||||
msg.Append("Could not retrieve directory "_ns);
|
||||
msg.Append(kDirectoryNames[aRequestedDir]);
|
||||
msg.Append(COLON);
|
||||
msg.Append(errorName);
|
||||
|
||||
aErr.ThrowUnknownError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
aResult = mDirectories[aRequestedDir];
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> PathUtils::DirectoryCache::GetDirectoryAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr,
|
||||
const Directory aRequestedDir) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
@ -481,10 +536,12 @@ nsresult PathUtils::DirectoryCache::PopulateDirectoriesImpl(
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(aRequestedDir < Directory::Count);
|
||||
|
||||
// We cannot have second request to populate any of these
|
||||
// directories if the first request succeeded, so assert that the
|
||||
// corresponding fields are void.
|
||||
MOZ_RELEASE_ASSERT(mDirectories[aRequestedDir].IsVoid());
|
||||
if (!mDirectories[aRequestedDir].IsVoid()) {
|
||||
// In between when this promise was dispatched to the main thread and now,
|
||||
// the directory cache has had this entry populated (via the on-main-thread
|
||||
// sync method).
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> path;
|
||||
|
||||
|
@ -67,12 +67,19 @@ class PathUtils final {
|
||||
|
||||
static bool IsAbsolute(const GlobalObject&, const nsAString& aPath);
|
||||
|
||||
static already_AddRefed<Promise> GetProfileDir(const GlobalObject& aGlobal,
|
||||
ErrorResult& aErr);
|
||||
static already_AddRefed<Promise> GetLocalProfileDir(
|
||||
static void GetProfileDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr);
|
||||
static void GetLocalProfileDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr);
|
||||
static void GetTempDirSync(const GlobalObject&, nsString& aResult,
|
||||
ErrorResult& aErr);
|
||||
|
||||
static already_AddRefed<Promise> GetProfileDirAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr);
|
||||
static already_AddRefed<Promise> GetTempDir(const GlobalObject& aGlobal,
|
||||
ErrorResult& aErr);
|
||||
static already_AddRefed<Promise> GetLocalProfileDirAsync(
|
||||
const GlobalObject& aGlobal, ErrorResult& aErr);
|
||||
static already_AddRefed<Promise> GetTempDirAsync(const GlobalObject& aGlobal,
|
||||
ErrorResult& aErr);
|
||||
|
||||
private:
|
||||
class DirectoryCache;
|
||||
@ -87,7 +94,8 @@ class PathUtils final {
|
||||
class PathUtils::DirectoryCache final {
|
||||
public:
|
||||
/**
|
||||
* A directory that can be requested via |GetDirectory|.
|
||||
* A directory that can be requested via |GetDirectorySync| or
|
||||
* |GetDirectoryAsync|.
|
||||
*/
|
||||
enum class Directory {
|
||||
/**
|
||||
@ -124,6 +132,9 @@ class PathUtils::DirectoryCache final {
|
||||
*/
|
||||
static DirectoryCache& Ensure(Maybe<DirectoryCache>& aCache);
|
||||
|
||||
void GetDirectorySync(nsString& aResult, ErrorResult& aErr,
|
||||
const Directory aRequestedDir);
|
||||
|
||||
/**
|
||||
* Request the path of a specific directory.
|
||||
*
|
||||
@ -136,9 +147,9 @@ class PathUtils::DirectoryCache final {
|
||||
*
|
||||
* @return A promise that resolves to the path of the requested directory.
|
||||
*/
|
||||
already_AddRefed<Promise> GetDirectory(const GlobalObject& aGlobalObject,
|
||||
ErrorResult& aErr,
|
||||
const Directory aRequestedDir);
|
||||
already_AddRefed<Promise> GetDirectoryAsync(const GlobalObject& aGlobalObject,
|
||||
ErrorResult& aErr,
|
||||
const Directory aRequestedDir);
|
||||
|
||||
private:
|
||||
using PopulateDirectoriesPromise = MozPromise<Ok, nsresult, false>;
|
||||
|
@ -4,3 +4,6 @@ support-files =
|
||||
|
||||
[test_constants.xhtml]
|
||||
[test_pathutils.html]
|
||||
[test_pathutils_worker.xhtml]
|
||||
support-files =
|
||||
pathutils_worker.js
|
||||
|
37
dom/system/tests/pathutils_worker.js
Normal file
37
dom/system/tests/pathutils_worker.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* eslint-env mozilla/chrome-worker */
|
||||
/* global finish */
|
||||
|
||||
"use strict";
|
||||
|
||||
importScripts("chrome://mochikit/content/tests/SimpleTest/WorkerSimpleTest.js");
|
||||
|
||||
self.onmessage = async function(message) {
|
||||
let expected = message.data;
|
||||
info("ON message");
|
||||
info(JSON.stringify(expected));
|
||||
const profileDir = await PathUtils.getProfileDir();
|
||||
is(
|
||||
profileDir,
|
||||
expected.profileDir,
|
||||
"PathUtils.profileDir() in a worker should match PathUtils.profileDir on main thread"
|
||||
);
|
||||
|
||||
const localProfileDir = await PathUtils.getLocalProfileDir();
|
||||
is(
|
||||
localProfileDir,
|
||||
expected.localProfileDir,
|
||||
"PathUtils.getLocalProfileDir() in a worker should match PathUtils.localProfileDir on main thread"
|
||||
);
|
||||
|
||||
const tempDir = await PathUtils.getTempDir();
|
||||
is(
|
||||
tempDir,
|
||||
expected.tempDir,
|
||||
"PathUtils.getTempDir() in a worker should match PathUtils.tempDir on main thread"
|
||||
);
|
||||
|
||||
finish();
|
||||
};
|
@ -8,6 +8,8 @@
|
||||
<title>PathUtils tests</title>
|
||||
</head>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/WorkerHandler.js"></script>
|
||||
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<script>
|
||||
"use strict";
|
||||
@ -471,34 +473,21 @@
|
||||
});
|
||||
|
||||
add_task(async function test_getDirectories() {
|
||||
const profile = await PathUtils.getProfileDir();
|
||||
is(
|
||||
profile,
|
||||
Services.dirsvc.get("ProfD", Ci.nsIFile).path,
|
||||
"PathUtils.getProfileDir() should match dirsvc"
|
||||
);
|
||||
|
||||
const localProfile = await PathUtils.getLocalProfileDir();
|
||||
is(
|
||||
localProfile,
|
||||
Services.dirsvc.get("ProfLD", Ci.nsIFile).path,
|
||||
"PathUtils.getLocalProfileDir() should match dirsvc"
|
||||
);
|
||||
|
||||
// See: nsAppDirectoryServiceDefs.h
|
||||
const tempDir = await PathUtils.getTempDir();
|
||||
if (AppConstants.MOZ_SANDBOX) {
|
||||
is(
|
||||
tempDir,
|
||||
Services.dirsvc.get("ContentTmpD", Ci.nsIFile).path,
|
||||
"PathUtils.getTempDir() should match dirsvc"
|
||||
);
|
||||
} else {
|
||||
is(
|
||||
tempDir,
|
||||
Services.dirsvc.get("TmpD", Ci.nsIFile).path,
|
||||
"PathUtils.getTempDir() should match dirsvc"
|
||||
);
|
||||
const tests = [
|
||||
["profileDir", "getProfileDir", "ProfD"],
|
||||
["localProfileDir", "getLocalProfileDir", "ProfLD"],
|
||||
["tempDir", "getTempDir", AppConstants.MOZ_SANDBOX ? "ContentTmpD" : "TmpD"],
|
||||
];
|
||||
|
||||
for (const [attrName, methName, dirConstant] of tests) {
|
||||
const expected = Services.dirsvc.get(dirConstant, Ci.nsIFile).path;
|
||||
|
||||
const attrValue = PathUtils[attrName];
|
||||
is(attrValue, expected, `PathUtils.${attrName} == Services.dirsvc.get("${dirConstant}", Ci.nsIFile).path`);
|
||||
|
||||
const methValue = await PathUtils[methName]();
|
||||
is(methValue, expected, `PathUtils.${methName}() == Services.dirsvc.get("${dirConstant}", Ci.nsIFile).path`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
39
dom/system/tests/test_pathutils_worker.xhtml
Normal file
39
dom/system/tests/test_pathutils_worker.xhtml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<window title="Testing PathUtils on a chrome worker thread"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/WorkerHandler.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function test() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
info("test_pathtuils_worker.xhtml: Starting test");
|
||||
|
||||
const worker = new ChromeWorker("pathutils_worker.js");
|
||||
info("test_pathtuils_worker.xhtml: ChromeWorker created");
|
||||
|
||||
listenForTests(worker, { verbose: false });
|
||||
worker.postMessage({
|
||||
profileDir: PathUtils.profileDir,
|
||||
localProfileDir: PathUtils.localProfileDir,
|
||||
tempDir: PathUtils.tempDir,
|
||||
});
|
||||
|
||||
info("test_pathtuils_worker.xhtml: Test running...");
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
<body xmlns="https://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result" />
|
||||
</window>
|
Loading…
x
Reference in New Issue
Block a user