Bug 1284785 part 2 - Report reason to console if a pointer lock request is denied. r?smaug
MozReview-Commit-ID: 9kSYxDQYGLz
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12279,28 +12279,32 @@ DispatchPointerLockChange(nsIDocument* a
new AsyncEventDispatcher(aTarget,
NS_LITERAL_STRING("mozpointerlockchange"),
true,
false);
asyncDispatcher->PostDOMEvent();
}
static void
-DispatchPointerLockError(nsIDocument* aTarget)
+DispatchPointerLockError(nsIDocument* aTarget, const char* aMessage)
{
if (!aTarget) {
return;
}
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(aTarget,
NS_LITERAL_STRING("mozpointerlockerror"),
true,
false);
asyncDispatcher->PostDOMEvent();
+ nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+ NS_LITERAL_CSTRING("DOM"), aTarget,
+ nsContentUtils::eDOM_PROPERTIES,
+ aMessage);
}
class PointerLockRequest final : public Runnable
{
public:
PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
: mElement(do_GetWeakReference(aElement))
, mDocument(do_GetWeakReference(aElement->OwnerDoc()))
@@ -12310,108 +12314,101 @@ public:
NS_IMETHOD Run() final;
private:
nsWeakPtr mElement;
nsWeakPtr mDocument;
bool mUserInputOrChromeCaller;
};
-static bool
-ShouldLockPointer(Element* aElement, Element* aCurrentLock,
- bool aNoFocusCheck = false)
+static const char*
+GetPointerLockError(Element* aElement, Element* aCurrentLock,
+ bool aNoFocusCheck = false)
{
// Check if pointer lock pref is enabled
if (!Preferences::GetBool("full-screen-api.pointer-lock.enabled")) {
- NS_WARNING("ShouldLockPointer(): Pointer Lock pref not enabled");
- return false;
+ return "PointerLockDeniedDisabled";
}
nsCOMPtr<nsIDocument> ownerDoc = aElement->OwnerDoc();
if (aCurrentLock && aCurrentLock->OwnerDoc() != ownerDoc) {
- NS_WARNING("ShouldLockPointer(): Existing pointer lock element in a different document");
- return false;
+ return "PointerLockDeniedOnUse";
}
if (!aElement->IsInUncomposedDoc()) {
- NS_WARNING("ShouldLockPointer(): Element without Document");
- return false;
+ return "PointerLockDeniedNotInDocument";
}
if (ownerDoc->GetSandboxFlags() & SANDBOXED_POINTER_LOCK) {
- NS_WARNING("ShouldLockPointer(): Document is sandboxed and doesn't allow pointer-lock");
- return false;
+ return "PointerLockDeniedSandboxed";
}
// Check if the element is in a document with a docshell.
if (!ownerDoc->GetContainer()) {
- return false;
+ return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowOuter> ownerWindow = ownerDoc->GetWindow();
if (!ownerWindow) {
- return false;
+ return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowInner> ownerInnerWindow = ownerDoc->GetInnerWindow();
if (!ownerInnerWindow) {
- return false;
+ return "PointerLockDeniedHidden";
}
if (ownerWindow->GetCurrentInnerWindow() != ownerInnerWindow) {
- return false;
+ return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowOuter> top = ownerWindow->GetScriptableTop();
if (!top || !top->GetExtantDoc() || top->GetExtantDoc()->Hidden()) {
- NS_WARNING("ShouldLockPointer(): Top document isn't visible.");
- return false;
+ return "PointerLockDeniedHidden";
}
if (!aNoFocusCheck) {
mozilla::ErrorResult rv;
if (!top->GetExtantDoc()->HasFocus(rv)) {
- NS_WARNING("ShouldLockPointer(): Top document isn't focused.");
- return false;
- }
- }
-
- return true;
+ return "PointerLockDeniedNotFocused";
+ }
+ }
+
+ return nullptr;
}
NS_IMETHODIMP
PointerLockRequest::Run()
{
nsCOMPtr<Element> e = do_QueryReferent(mElement);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
nsDocument* d = static_cast<nsDocument*>(doc.get());
- if (!e || !d || e->GetUncomposedDoc() != d) {
- DispatchPointerLockError(d);
- return NS_OK;
- }
-
- nsCOMPtr<Element> pointerLockedElement =
- do_QueryReferent(EventStateManager::sPointerLockedElement);
- if (e == pointerLockedElement) {
- DispatchPointerLockChange(d);
- return NS_OK;
- }
-
- // Note, we must bypass focus change, so pass true as the last parameter!
- if (!ShouldLockPointer(e, pointerLockedElement, true)) {
- DispatchPointerLockError(d);
- return NS_OK;
- }
-
+ const char* error = nullptr;
+ if (!e || !d || !e->GetUncomposedDoc()) {
+ error = "PointerLockDeniedNotInDocument";
+ } else if (e->GetUncomposedDoc() != d) {
+ error = "PointerLockDeniedMovedDocument";
+ }
+ if (!error) {
+ nsCOMPtr<Element> pointerLockedElement =
+ do_QueryReferent(EventStateManager::sPointerLockedElement);
+ if (e == pointerLockedElement) {
+ DispatchPointerLockChange(d);
+ return NS_OK;
+ }
+ // Note, we must bypass focus change, so pass true as the last parameter!
+ error = GetPointerLockError(e, pointerLockedElement, true);
+ }
// If it is neither user input initiated, nor requested in fullscreen,
// it should be rejected.
- if (!mUserInputOrChromeCaller && !doc->GetFullscreenElement()) {
- DispatchPointerLockError(d);
- return NS_OK;
- }
-
- if (!d->SetPointerLock(e, NS_STYLE_CURSOR_NONE)) {
- DispatchPointerLockError(d);
+ if (!error && !mUserInputOrChromeCaller && !doc->GetFullscreenElement()) {
+ error = "PointerLockDeniedNotInputDriven";
+ }
+ if (!error && !d->SetPointerLock(e, NS_STYLE_CURSOR_NONE)) {
+ error = "PointerLockDeniedFailedToLock";
+ }
+ if (error) {
+ DispatchPointerLockError(d, error);
return NS_OK;
}
e->SetPointerLock();
EventStateManager::sPointerLockedElement = do_GetWeakReference(e);
EventStateManager::sPointerLockedDoc = do_GetWeakReference(doc);
NS_ASSERTION(EventStateManager::sPointerLockedElement &&
EventStateManager::sPointerLockedDoc,
@@ -12433,18 +12430,18 @@ nsDocument::RequestPointerLock(Element*
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (aElement == pointerLockedElement) {
DispatchPointerLockChange(this);
return;
}
- if (!ShouldLockPointer(aElement, pointerLockedElement)) {
- DispatchPointerLockError(this);
+ if (const char* msg = GetPointerLockError(aElement, pointerLockedElement)) {
+ DispatchPointerLockError(this, msg);
return;
}
bool userInputOrChromeCaller = EventStateManager::IsHandlingUserInput() ||
nsContentUtils::IsCallerChrome();
NS_DispatchToMainThread(new PointerLockRequest(aElement,
userInputOrChromeCaller));
}
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -73,16 +73,25 @@ FullscreenDeniedNotInputDriven=Request f
FullscreenDeniedNotInDocument=Request for fullscreen was denied because requesting element is no longer in its document.
FullscreenDeniedMovedDocument=Request for fullscreen was denied because requesting element has moved document.
FullscreenDeniedLostWindow=Request for fullscreen was denied because we no longer have a window.
FullscreenDeniedSubDocFullscreen=Request for fullscreen was denied because a subdocument of the document requesting fullscreen is already fullscreen.
FullscreenDeniedNotDescendant=Request for fullscreen was denied because requesting element is not a descendant of the current fullscreen element.
FullscreenDeniedNotFocusedTab=Request for fullscreen was denied because requesting element is not in the currently focused tab.
RemovedFullscreenElement=Exited fullscreen because fullscreen element was removed from document.
FocusedWindowedPluginWhileFullscreen=Exited fullscreen because windowed plugin was focused.
+PointerLockDeniedDisabled=Request for pointer lock was denied because Pointer Lock API is disabled by user preference.
+PointerLockDeniedOnUse=Request for pointer lock was denied because the pointer is currently controlled by a different document.
+PointerLockDeniedNotInDocument=Request for pointer lock was denied because requesting element is not in a document.
+PointerLockDeniedSandboxed=Request for pointer lock was denied because Pointer Lock API is restricted via sandbox.
+PointerLockDeniedHidden=Request for pointer lock was denied because the document is not visible.
+PointerLockDeniedNotFocused=Request for pointer lock was denied because the document is not focused.
+PointerLockDeniedMovedDocument=Request for pointer lock was denied because requesting element has moved document.
+PointerLockDeniedNotInputDriven=Request for pointer lock was denied because Element.requestPointerLock() was not called from inside a short running user-generated event handler, and the document is not in full screen.
+PointerLockDeniedFailedToLock=Request for pointer lock was denied because the browser failed to lock the pointer.
HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn’t implement nsIWritablePropertyBag2.
ResponseTypeSyncXHRWarning=Use of XMLHttpRequest’s responseType attribute is no longer supported in the synchronous mode in window context.
TimeoutSyncXHRWarning=Use of XMLHttpRequest’s timeout attribute is not supported in the synchronous mode in window context.
JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
# LOCALIZATION NOTE: Do not translate AudioBufferSourceNode
MediaBufferSourceNodeResampleOutOfMemory=Insufficient memory to resample the AudioBufferSourceNode for playback.
# LOCALIZATION NOTE: Do not translate decodeAudioData.