mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 1759152 - Expose file system to workers. r=dom-storage-reviewers,jesup,janv
Depends on D149983 Differential Revision: https://phabricator.services.mozilla.com/D140862
This commit is contained in:
parent
bbf960e82c
commit
f1f7e8a209
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsNetCID.h"
|
||||
#include "mozilla/dom/FileSystemTypes.h"
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
@ -65,14 +66,19 @@ mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot(
|
||||
nsAutoCString origin =
|
||||
quota::QuotaManager::GetOriginFromValidatedPrincipalInfo(mPrincipalInfo);
|
||||
|
||||
// This opens the quota manager, which has to be done on PBackground
|
||||
auto res =
|
||||
fs::data::FileSystemDataManager::CreateFileSystemDataManager(origin);
|
||||
QM_TRY(OkIf(res.isErr()), IPC_OK(), [aResolver](const auto&) {
|
||||
aResolver(fs::FileSystemGetRootResponse(NS_ERROR_UNEXPECTED));
|
||||
});
|
||||
auto sendBackError = [aResolver](const auto& aRv) {
|
||||
aResolver(fs::FileSystemGetRootResponse(aRv));
|
||||
};
|
||||
|
||||
fs::EntryId rootId = fs::data::GetRootHandle(origin);
|
||||
|
||||
// This opens the quota manager, which has to be done on PBackground
|
||||
QM_TRY_UNWRAP(
|
||||
fs::data::FileSystemDataManager * dataRaw,
|
||||
fs::data::FileSystemDataManager::CreateFileSystemDataManager(origin),
|
||||
IPC_OK(), sendBackError);
|
||||
UniquePtr<fs::data::FileSystemDataManager> data(dataRaw);
|
||||
|
||||
UniquePtr<fs::data::FileSystemDataManager> data(res.unwrap());
|
||||
nsCOMPtr<nsIThread> pbackground = NS_GetCurrentThread();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
@ -86,22 +92,19 @@ mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot(
|
||||
// We'll have to thread-hop back to this thread to respond. We could
|
||||
// just have the create be one-way, then send the actual request on the
|
||||
// new channel, but that's an extra IPC instead.
|
||||
InvokeAsync(
|
||||
taskqueue, __func__,
|
||||
[origin, parentEp = std::move(aParentEp), aResolver,
|
||||
data = std::move(data), taskqueue, pbackground]() mutable {
|
||||
RefPtr<OriginPrivateFileSystemParent> parent =
|
||||
new OriginPrivateFileSystemParent(taskqueue);
|
||||
if (!parentEp.Bind(parent)) {
|
||||
auto response = fs::FileSystemGetRootResponse(NS_ERROR_FAILURE);
|
||||
return RootPromise::CreateAndReject(response, __func__);
|
||||
}
|
||||
|
||||
// Send response back to pbackground to send to child
|
||||
auto response =
|
||||
fs::FileSystemGetRootResponse(fs::data::GetRootHandle(origin));
|
||||
return RootPromise::CreateAndResolve(response, __func__);
|
||||
})
|
||||
InvokeAsync(taskqueue, __func__,
|
||||
[origin, parentEp = std::move(aParentEp), aResolver, rootId,
|
||||
data = std::move(data), taskqueue, pbackground]() mutable {
|
||||
RefPtr<OriginPrivateFileSystemParent> parent =
|
||||
new OriginPrivateFileSystemParent(taskqueue);
|
||||
if (!parentEp.Bind(parent)) {
|
||||
auto response =
|
||||
fs::FileSystemGetRootResponse(NS_ERROR_FAILURE);
|
||||
return RootPromise::CreateAndReject(response, __func__);
|
||||
}
|
||||
// Send response back to pbackground to send to child
|
||||
return RootPromise::CreateAndResolve(rootId, __func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver](const RootPromise::ResolveOrRejectValue& aValue) {
|
||||
if (aValue.IsReject()) {
|
||||
|
@ -3,19 +3,192 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
async function test1() {
|
||||
const { nsresult } = await require_module("dom/fs/test/common/nsresult.js");
|
||||
exported_symbols.testGetDirectoryDoesNotThrow = async function() {
|
||||
await navigator.storage.getDirectory();
|
||||
|
||||
Assert.ok(true, "Should not have thrown");
|
||||
};
|
||||
|
||||
exported_symbols.testGetDirectoryKindIsDirectory = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
Assert.equal(root.kind, "directory");
|
||||
};
|
||||
|
||||
exported_symbols.testDirectoryHandleStringConversion = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
Assert.equal(
|
||||
"" + root,
|
||||
"[object FileSystemDirectoryHandle]",
|
||||
"Is directoryHandle convertible to string?"
|
||||
);
|
||||
};
|
||||
|
||||
exported_symbols.testNewDirectoryHandleFromPrototype = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
try {
|
||||
await navigator.storage.getDirectory();
|
||||
|
||||
Object.create(root.prototype);
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (e) {
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.ok(
|
||||
e.result === nsresult.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw right result code"
|
||||
Assert.ok(ex instanceof TypeError, "Threw the right error type");
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testDirectoryHandleSupportsKeysIterator = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.keys();
|
||||
Assert.ok(!!it, "Does root support keys iterator?");
|
||||
};
|
||||
|
||||
exported_symbols.testKeysIteratorNextIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.keys();
|
||||
Assert.ok(!!it, "Does root support keys iterator?");
|
||||
|
||||
try {
|
||||
await it.next();
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testDirectoryHandleSupportsValuesIterator = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.values();
|
||||
Assert.ok(!!it, "Does root support values iterator?");
|
||||
};
|
||||
|
||||
exported_symbols.testValuesIteratorNextIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.values();
|
||||
Assert.ok(!!it, "Does root support values iterator?");
|
||||
|
||||
try {
|
||||
await it.next();
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testDirectoryHandleSupportsEntriesIterator = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.entries();
|
||||
Assert.ok(!!it, "Does root support entries iterator?");
|
||||
};
|
||||
|
||||
exported_symbols.testEntriesIteratorNextIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
const it = await root.entries();
|
||||
Assert.ok(!!it, "Does root support entries iterator?");
|
||||
|
||||
try {
|
||||
await it.next();
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testGetFileHandleIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const allowCreate = { create: true };
|
||||
|
||||
try {
|
||||
await root.getFileHandle("name", allowCreate);
|
||||
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testGetDirectoryHandleIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const allowCreate = { create: true };
|
||||
|
||||
try {
|
||||
await root.getDirectoryHandle("name", allowCreate);
|
||||
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testRemoveEntryIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const removeOptions = { recursive: true };
|
||||
|
||||
try {
|
||||
await root.removeEntry("root", removeOptions);
|
||||
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exported_symbols.testResolveIsCallable = async function() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
|
||||
try {
|
||||
await root.resolve(root);
|
||||
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(true, "Should have thrown");
|
||||
Assert.equal(
|
||||
ex.result,
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED,
|
||||
"Threw the right result code"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
for (const [key, value] of Object.entries(exported_symbols)) {
|
||||
Object.defineProperty(value, "name", {
|
||||
value: key,
|
||||
writable: false,
|
||||
});
|
||||
}
|
||||
exported_symbols.test1 = test1;
|
||||
|
@ -36,7 +36,7 @@ async function run_test_in_worker(script) {
|
||||
|
||||
// XXX It would be nice if we could call add_setup here (xpcshell-test and
|
||||
// browser-test support it.
|
||||
add_task(async function() {
|
||||
add_task(async function setup() {
|
||||
const { setStoragePrefs, clearStoragesForOrigin } = await import(
|
||||
"/tests/dom/quota/test/modules/StorageUtils.js"
|
||||
);
|
||||
|
@ -11,11 +11,19 @@
|
||||
|
||||
<script type="text/javascript" src="head.js"></script>
|
||||
<script type="text/javascript">
|
||||
add_task(async function test_1() {
|
||||
const { test1 } = await require_module("dom/fs/test/common/test_basics.js");
|
||||
// XXX This should be done in a task, but SimpleTest currently doesn't
|
||||
// support adding new tasks during a task execution.
|
||||
async function init() {
|
||||
const testSet = "dom/fs/test/common/test_basics.js";
|
||||
|
||||
await test1();
|
||||
});
|
||||
const testCases = await require_module(testSet);
|
||||
|
||||
Object.values(testCases).forEach(testItem => {
|
||||
add_task(testItem);
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
@ -3,8 +3,9 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
add_task(async function test_1() {
|
||||
const { test1 } = await require_module("dom/fs/test/common/test_basics.js");
|
||||
|
||||
await test1();
|
||||
add_task(async function init() {
|
||||
const testCases = await require_module("dom/fs/test/common/test_basics.js");
|
||||
Object.values(testCases).forEach(async testItem => {
|
||||
add_task(testItem);
|
||||
});
|
||||
});
|
||||
|
@ -3,8 +3,12 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
add_task(async function test_1() {
|
||||
const { test1 } = await require_module("dom/fs/test/common/test_basics.js");
|
||||
add_task(async function init() {
|
||||
const testSet = "dom/fs/test/common/test_basics.js";
|
||||
|
||||
await test1();
|
||||
const testCases = await require_module(testSet);
|
||||
|
||||
Object.values(testCases).forEach(testItem => {
|
||||
add_task(testItem);
|
||||
});
|
||||
});
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include "ErrorList.h"
|
||||
#include "fs/FileSystemRequestHandler.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "js/CallArgs.h"
|
||||
#include "js/TypeDecls.h"
|
||||
@ -754,13 +755,16 @@ already_AddRefed<Promise> StorageManager::Estimate(ErrorResult& aRv) {
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> StorageManager::GetDirectory(ErrorResult& aRv) {
|
||||
RefPtr<Promise> promise = Promise::Create(GetParentObject(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
MOZ_ASSERT(mOwner);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mOwner, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
promise->MaybeReject(NS_ERROR_NOT_IMPLEMENTED);
|
||||
MOZ_ASSERT(promise);
|
||||
|
||||
fs::FileSystemRequestHandler{}.GetRoot(promise);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,5 @@ FINAL_LIBRARY = "xul"
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/caps",
|
||||
"/dom/fs/include",
|
||||
]
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
// Just a wrapper around SimpleTest related functions for now.
|
||||
export const Assert = {
|
||||
ok(value, message) {
|
||||
ok(value, message);
|
||||
},
|
||||
ok,
|
||||
equal: is,
|
||||
};
|
||||
|
@ -20,6 +20,10 @@ export async function runTestInWorker(script) {
|
||||
ok(data.value, data.message);
|
||||
break;
|
||||
|
||||
case "is":
|
||||
is(data.a, data.b, data.message);
|
||||
break;
|
||||
|
||||
case "info":
|
||||
info(data.message);
|
||||
break;
|
||||
@ -27,6 +31,11 @@ export async function runTestInWorker(script) {
|
||||
case "finish":
|
||||
resolve();
|
||||
break;
|
||||
|
||||
case "failure":
|
||||
ok(false, "Worker had a failure: " + data.message);
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,4 +11,12 @@ const Assert = {
|
||||
message,
|
||||
});
|
||||
},
|
||||
equal(a, b, message) {
|
||||
postMessage({
|
||||
op: "is",
|
||||
a,
|
||||
b,
|
||||
message,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ const Cr = {
|
||||
function add_task(func) {
|
||||
if (!add_task.tasks) {
|
||||
add_task.tasks = [];
|
||||
add_task.index = 0;
|
||||
}
|
||||
|
||||
add_task.tasks.push(func);
|
||||
@ -20,17 +21,35 @@ addEventListener("message", async function onMessage(event) {
|
||||
postMessage({ op: "info", message });
|
||||
}
|
||||
|
||||
function executeSoon(callback) {
|
||||
const channel = new MessageChannel();
|
||||
channel.port1.postMessage("");
|
||||
channel.port2.onmessage = function() {
|
||||
callback();
|
||||
};
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (add_task.index < add_task.tasks.length) {
|
||||
const task = add_task.tasks[add_task.index++];
|
||||
info("add_task | Entering test " + task.name);
|
||||
task()
|
||||
.then(function() {
|
||||
executeSoon(runNextTest);
|
||||
info("add_task | Leaving test " + task.name);
|
||||
})
|
||||
.catch(function(ex) {
|
||||
postMessage({ op: "failure", message: "" + ex });
|
||||
});
|
||||
} else {
|
||||
postMessage({ op: "finish" });
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener("message", onMessage);
|
||||
|
||||
const data = event.data;
|
||||
importScripts(...data);
|
||||
|
||||
let task;
|
||||
while ((task = add_task.tasks.shift())) {
|
||||
info("add_task | Entering test " + task.name);
|
||||
await task();
|
||||
info("add_task | Leaving test " + task.name);
|
||||
}
|
||||
|
||||
postMessage({ op: "finish" });
|
||||
executeSoon(runNextTest);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user