Bug 687687 - Log helpful messages to web-console when full-screen is denied/revoked. r=bz
authorChris Pearce <chris@pearce.org.nz>
Tue, 22 Nov 2011 10:23:48 +1300
changeset 80585 f6be9ad957b1963884b9dc599ac72e34bf7c1c92
parent 80584 816d3aca13c42a39f317852e66f3e92f49fe7254
child 80586 3b3c9e09abe39372b3d8cb488f1c7e827db9299b
push id3513
push usercpearce@mozilla.com
push dateMon, 21 Nov 2011 21:28:52 +0000
treeherdermozilla-inbound@f6be9ad957b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs687687
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 687687 - Log helpful messages to web-console when full-screen is denied/revoked. r=bz
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericElement.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsHTMLSharedObjectElement.cpp
dom/locales/en-US/chrome/dom/dom.properties
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8601,38 +8601,68 @@ public:
   nsRefPtr<Element> mElement;
   nsCOMPtr<nsIDocument> mDoc;
   bool mWasCallerChrome;
 };
 
 void
 nsDocument::AsyncRequestFullScreen(Element* aElement)
 {
+  NS_ASSERTION(aElement,
+    "Must pass non-null element to nsDocument::AsyncRequestFullScreen");
   if (!aElement) {
     return;
   }
   // Request full-screen asynchronously.
   nsCOMPtr<nsIRunnable> event(new nsCallRequestFullScreen(aElement));
   NS_DispatchToCurrentThread(event);
 }
 
+static void
+LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
+{
+  if (!aLogFailure) {
+    return;
+  }
+  nsRefPtr<nsPLDOMEvent> e =
+    new nsPLDOMEvent(aDoc,
+                     NS_LITERAL_STRING("mozfullscreenerror"),
+                     true,
+                     false);
+  e->PostDOMEvent();
+  nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                  aMessage,
+                                  nsnull, 0, nsnull,
+                                  EmptyString(), 0, 0,
+                                  nsIScriptError::warningFlag,
+                                  "DOM", aDoc);
+}
+
 void
 nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
 {
-  if (!aElement ||
-      !aElement->IsInDoc() ||
-      aElement->OwnerDoc() != this ||
-      !IsFullScreenEnabled(aWasCallerChrome) ||
-      !GetWindow()) {
-    nsRefPtr<nsPLDOMEvent> e =
-      new nsPLDOMEvent(this,
-                       NS_LITERAL_STRING("mozfullscreenerror"),
-                       true,
-                       false);
-    e->PostDOMEvent();
+  NS_ASSERTION(aElement,
+    "Must pass non-null element to nsDocument::RequestFullScreen");
+  if (!aElement) {
+    return;
+  }
+  if (!aElement->IsInDoc()) {
+    LogFullScreenDenied(true, "FullScreenDeniedNotInDocument", this);
+    return;
+  }
+  if (aElement->OwnerDoc() != this) {
+    LogFullScreenDenied(true, "FullScreenDeniedMovedDocument", this);
+    return;
+  }
+  if (!GetWindow()) {
+    LogFullScreenDenied(true, "FullScreenDeniedLostWindow", this);
+    return;
+  }
+  if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
+    // IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
     return;
   }
 
   // Turn off full-screen state in all documents which were previously
   // full-screen but which shouldn't be after this request is granted.
   // Note commonAncestor will be null when in a separate browser window
   // to the requesting document.
   nsIDocument* commonAncestor = nsnull;
@@ -8717,47 +8747,55 @@ nsDocument::GetMozFullScreen(bool *aFull
   *aFullScreen = IsFullScreenDoc();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
 {
   NS_ENSURE_ARG_POINTER(aFullScreen);
-  *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome());
+  *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
   return NS_OK;
 }
 
 bool
-nsDocument::IsFullScreenEnabled(bool aCallerIsChrome)
+nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
 {
   if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
     // Chrome code can always use the full-screen API, provided it's not
     // explicitly disabled. Note IsCallerChrome() returns true when running
     // in an nsRunnable, so don't use GetMozFullScreenEnabled() from an
     // nsRunnable!
     return true;
   }
 
-  if (!nsContentUtils::IsFullScreenApiEnabled() ||
-      nsContentUtils::HasPluginWithUncontrolledEventDispatch(this) ||
-      !IsVisible()) {
+  if (!nsContentUtils::IsFullScreenApiEnabled()) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedDisabled", this);
+    return false;
+  }
+  if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedPlugins", this);
+    return false;
+  }
+  if (!IsVisible()) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
     return false;
   }
 
   // Ensure that all ancestor <iframe> elements have the mozallowfullscreen
   // boolean attribute set.
   nsINode* node = static_cast<nsINode*>(this);
   do {
     nsIContent* content = static_cast<nsIContent*>(node);
     if (content->IsHTML(nsGkAtoms::iframe) &&
         !content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
       // The node requesting fullscreen, or one of its crossdoc ancestors,
       // is an iframe which doesn't have the "mozalllowfullscreen" attribute.
       // This request is not authorized by the parent document.
+      LogFullScreenDenied(aLogFailure, "FullScreenDeniedIframeDisallowed", this);
       return false;
     }
     node = nsContentUtils::GetCrossDocParentNode(node);
   } while (node);
 
   return true;
 }
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -973,17 +973,19 @@ public:
 protected:
   friend class nsNodeUtils;
 
   // Returns true if a request for DOM full-screen is currently enabled in
   // this document. This returns true if there are no windowed plugins in this
   // doc tree, and if the document is visible, and if the api is not
   // disabled by pref. aIsCallerChrome must contain the return value of
   // nsContentUtils::IsCallerChrome() from the context we're checking.
-  bool IsFullScreenEnabled(bool aIsCallerChrome);
+  // If aLogFailure is true, an appropriate warning message is logged to the
+  // console, and a "mozfullscreenerror" event is dispatched to this document.
+  bool IsFullScreenEnabled(bool aIsCallerChrome, bool aLogFailure);
 
   /**
    * Check that aId is not empty and log a message to the console
    * service if it is.
    * @returns true if aId looks correct, false otherwise.
    */
   inline bool CheckGetElementByIdArg(const nsAString& aId)
   {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3062,16 +3062,22 @@ nsGenericElement::UnbindFromTree(bool aD
   // Make sure to unbind this node before doing the kids
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
 
   if (aNullParent) {
     if (IsFullScreenAncestor(this)) {
       // The element being removed is an ancestor of the full-screen element,
       // exit full-screen state.
+      nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                      "RemovedFullScreenElement",
+                                      nsnull, 0, nsnull,
+                                      EmptyString(), 0, 0,
+                                      nsIScriptError::warningFlag,
+                                      "DOM", OwnerDoc());      
       OwnerDoc()->CancelFullScreen();
     }
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nsnull;
     }
     SetParentIsContent(false);
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -113,16 +113,17 @@
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHtml5Module.h"
 #include "nsITextControlElement.h"
 #include "mozilla/dom/Element.h"
 #include "nsHTMLFieldSetElement.h"
 #include "nsHTMLMenuElement.h"
 #include "nsPLDOMEvent.h"
+#include "nsIScriptError.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/FromParser.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #include "nsThreadUtils.h"
@@ -3463,16 +3464,22 @@ nsGenericHTMLElement::Focus()
 nsresult nsGenericHTMLElement::MozRequestFullScreen()
 {
   // Only grant full-screen requests if this is called from inside a trusted
   // event handler (i.e. inside an event handler for a user initiated event).
   // This stops the full-screen from being abused similar to the popups of old,
   // and it also makes it harder for bad guys' script to go full-screen and
   // spoof the browser chrome/window and phish logins etc.
   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
+    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                    "FullScreenDeniedNotInputDriven",
+                                    nsnull, 0, nsnull,
+                                    EmptyString(), 0, 0,
+                                    nsIScriptError::warningFlag,
+                                    "DOM", OwnerDoc());
     nsRefPtr<nsPLDOMEvent> e =
       new nsPLDOMEvent(OwnerDoc(),
                        NS_LITERAL_STRING("mozfullscreenerror"),
                        true,
                        false);
     e->PostDOMEvent();
     return NS_OK;
   }
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -44,16 +44,17 @@
 #include "nsDOMError.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsIDOMHTMLEmbedElement.h"
 #include "nsThreadUtils.h"
 #include "nsIDOMGetSVGDocument.h"
 #include "nsIDOMSVGDocument.h"
+#include "nsIScriptError.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsHTMLSharedObjectElement : public nsGenericHTMLElement
                                 , public nsObjectLoadingContent
                                 , public nsIDOMHTMLAppletElement
                                 , public nsIDOMHTMLEmbedElement
@@ -292,16 +293,22 @@ nsHTMLSharedObjectElement::BindToTree(ns
   if (aDocument &&
       aDocument->IsFullScreenDoc() &&
       nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
     // This content contains a windowed plugin for which we don't control
     // event dispatch, and we're in full-screen mode. Exit full-screen mode
     // to prevent phishing attacks.
     NS_DispatchToCurrentThread(
       NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
+    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                    "AddedWindowedPluginWhileFullScreen",
+                                    nsnull, 0, nsnull,
+                                    EmptyString(), 0, 0,
+                                    nsIScriptError::warningFlag,
+                                    "DOM", aDocument);           
   }
 #endif
   return NS_OK;
 }
 
 void
 nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep,
                                           bool aNullParent)
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -110,10 +110,20 @@ TextContentWarning=Use of attributes' te
 EnablePrivilegeWarning=Use of enablePrivilege is deprecated.  Please use code that runs with the system principal (e.g. an extension) instead.
 PositionWarning=Use of XMLHttpRequest's progress events' position attribute is deprecated.
 TotalSizeWarning=Use of XMLHttpRequest's progress events' totalSize attribute is deprecated.
 nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated.  Please use JSON.parse instead.
 nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated.  Please use JSON.stringify instead.
 nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
 InputEncodingWarning=Use of inputEncoding is deprecated.
 GlobalStorageWarning=Use of globalStorage is deprecated. Please use localStorage instead.
+FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
+FullScreenDeniedPlugins=Request for full-screen was denied because a document on this page contains a windowed plugin.
+FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
+FullScreenDeniedIframeDisallowed=Request for full-screen was denied because at least one of the document's containing iframes does not have a "mozallowfullscreen" attribute.
+FullScreenDeniedNotInputDriven=Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler.
+FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
+FullScreenDeniedMovedDocument=Request for full-screen was denied because requesting element has moved document.
+FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
+RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
+AddedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was added to document.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.