Bug 1284785 part 2 - Report reason to console if a pointer lock request is denied. r?smaug draft
authorXidorn Quan <me@upsuper.org>
Mon, 11 Jul 2016 16:59:18 +1000
changeset 386489 b379da33ff7dd5af866d020a6cf9f530bbc664e9
parent 386488 fa48db36e10e49eeac62e62ece08d7ede4139843
child 525122 191f867cf6e1a71297ca457f48af50b31cd236aa
push id22715
push userxquan@mozilla.com
push dateMon, 11 Jul 2016 23:37:05 +0000
reviewerssmaug
bugs1284785
milestone50.0a1
Bug 1284785 part 2 - Report reason to console if a pointer lock request is denied. r?smaug MozReview-Commit-ID: 9kSYxDQYGLz
dom/base/nsDocument.cpp
dom/locales/en-US/chrome/dom/dom.properties
--- 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.