mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1738438 - Throw InvalidStateError as early as possible on LockManager r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D130504
This commit is contained in:
parent
f3d8d04ae4
commit
79ffe182a6
@ -35,7 +35,6 @@ JSObject* LockManager::WrapObject(JSContext* aCx,
|
||||
LockManager::LockManager(nsIGlobalObject* aGlobal) : mOwner(aGlobal) {
|
||||
Maybe<ClientInfo> clientInfo = aGlobal->GetClientInfo();
|
||||
if (!clientInfo) {
|
||||
// TODO: https://github.com/WICG/web-locks/issues/78
|
||||
return;
|
||||
}
|
||||
|
||||
@ -113,6 +112,16 @@ already_AddRefed<Promise> LockManager::Request(const nsAString& aName,
|
||||
const LockOptions& aOptions,
|
||||
LockGrantedCallback& aCallback,
|
||||
ErrorResult& aRv) {
|
||||
if (!mOwner->GetClientInfo()) {
|
||||
// We do have nsPIDOMWindowInner::IsFullyActive for this kind of check,
|
||||
// but this should be sufficient here as unloaded iframe is the only
|
||||
// non-fully-active case that Web Locks should worry about (since it does
|
||||
// not enter bfcache).
|
||||
aRv.ThrowInvalidStateError(
|
||||
"The document of the lock manager is not fully active");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mOwner->GetStorageAccess() <= StorageAccess::eDeny) {
|
||||
// Step 4: If origin is an opaque origin, then return a promise rejected
|
||||
// with a "SecurityError" DOMException.
|
||||
@ -121,15 +130,14 @@ already_AddRefed<Promise> LockManager::Request(const nsAString& aName,
|
||||
aRv.ThrowSecurityError("request() is not allowed in this context");
|
||||
return nullptr;
|
||||
}
|
||||
if (!ValidateRequestArguments(aName, aOptions, aRv)) {
|
||||
|
||||
if (!mActor) {
|
||||
aRv.ThrowNotSupportedError(
|
||||
"Web Locks API is not enabled for this kind of document");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mActor) {
|
||||
// TODO: https://github.com/WICG/web-locks/issues/78
|
||||
aRv.ThrowInvalidStateError(
|
||||
"The document of the lock manager is not fully active or web locks "
|
||||
"aren't enabled for the document.");
|
||||
if (!ValidateRequestArguments(aName, aOptions, aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -143,16 +151,20 @@ already_AddRefed<Promise> LockManager::Request(const nsAString& aName,
|
||||
};
|
||||
|
||||
already_AddRefed<Promise> LockManager::Query(ErrorResult& aRv) {
|
||||
if (!mOwner->GetClientInfo()) {
|
||||
aRv.ThrowInvalidStateError(
|
||||
"The document of the lock manager is not fully active");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mOwner->GetStorageAccess() <= StorageAccess::eDeny) {
|
||||
aRv.ThrowSecurityError("query() is not allowed in this context");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mActor) {
|
||||
// TODO: https://github.com/WICG/web-locks/issues/78
|
||||
aRv.ThrowInvalidStateError(
|
||||
"The document of the lock manager is not fully active or web locks "
|
||||
"aren't enabled for the document.");
|
||||
aRv.ThrowNotSupportedError(
|
||||
"Web Locks API is not enabled for this kind of document");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Web Locks API: Non-fully-active documents</title>
|
||||
<link rel=help href="https://wicg.github.io/web-locks/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/helpers.js"></script>
|
||||
|
||||
<div></div>
|
||||
|
||||
<script>
|
||||
function createNonFullyActiveIframe(src) {
|
||||
const iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
const { navigator, DOMException, postMessage } = iframe.contentWindow;
|
||||
iframe.remove();
|
||||
return { iframe, navigator, DOMException, postMessage };
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
const { navigator, DOMException } = createNonFullyActiveIframe();
|
||||
const p = navigator.locks.request("foo", t.unreached_func());
|
||||
await promise_rejects_dom(t, "InvalidStateError", DOMException, p, "Request should explicitly fail");
|
||||
}, "request() on non-fully-active document must fail");
|
||||
|
||||
promise_test(async t => {
|
||||
const { navigator, DOMException } = createNonFullyActiveIframe();
|
||||
const p = navigator.locks.query();
|
||||
await promise_rejects_dom(t, "InvalidStateError", DOMException, p, "Query should explicitly fail");
|
||||
}, "query() on a non-fully-active document must fail");
|
||||
|
||||
promise_test(async t => {
|
||||
const { navigator, DOMException, postMessage } = createNonFullyActiveIframe();
|
||||
|
||||
const p = navigator.locks.request("-", t.unreached_func());
|
||||
await promise_rejects_dom(t, "InvalidStateError", DOMException, p, "Request should explicitly fail");
|
||||
}, "request()'s fully-active check happens earlier than name validation");
|
||||
|
||||
promise_test(async t => {
|
||||
const { iframe, navigator, DOMException } = createNonFullyActiveIframe();
|
||||
document.body.append(iframe);
|
||||
t.add_cleanup(() => iframe.remove());
|
||||
|
||||
// Appending should create a new browsing context with a new Navigator object
|
||||
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:insert-an-element-into-a-document
|
||||
// https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object:associated-navigator
|
||||
assert_not_equals(navigator, iframe.contentWindow.navigator, "Navigator object changes");
|
||||
assert_not_equals(navigator.locks, iframe.contentWindow.navigator.locks, "LockManager object changes");
|
||||
|
||||
const p = navigator.locks.request("foo", t.unreached_func());
|
||||
await promise_rejects_dom(t, "InvalidStateError", DOMException, p, "Request on the previous LockManager still must fail");
|
||||
}, "Reactivated iframe must not reuse the previous LockManager");
|
||||
|
||||
promise_test(async t => {
|
||||
const iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
const worker = new iframe.contentWindow.Worker("resources/worker.js");
|
||||
|
||||
const name = uniqueName(t);
|
||||
await postToWorkerAndWait(worker, { op: 'request', name });
|
||||
|
||||
let query = await navigator.locks.query();
|
||||
assert_equals(query.held.length, 1, "One lock is present");
|
||||
|
||||
iframe.remove();
|
||||
|
||||
const lock = await navigator.locks.request(name, lock => lock);
|
||||
assert_equals(lock.name, name, "The following lock should be processed");
|
||||
|
||||
query = await navigator.locks.query();
|
||||
assert_equals(query.held.length, 0, "No lock is present");
|
||||
}, "Workers owned by an unloaded iframe must release their locks");
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user