Bug 826325 - Handle preventDefault on mozbrowserwindowopen events r=bz
authorWes Johnston <wjohnston@mozilla.com>
Mon, 09 Sep 2013 21:18:46 -0700
changeset 146396 bd53e981282f9ed59ca35ce59776c2f94e9f6e7d
parent 146317 ea33604f6232a07d3e4be77718226d569490407f
child 146397 32e968bcba07e2296ea6ab9f9a7c20a939f5b025
push id25260
push userryanvm@gmail.com
push dateWed, 11 Sep 2013 00:29:30 +0000
treeherdermozilla-central@f73bed2856a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs826325
milestone26.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 826325 - Handle preventDefault on mozbrowserwindowopen events r=bz
dom/browser-element/BrowserElementParent.cpp
dom/browser-element/BrowserElementParent.h
dom/browser-element/Makefile.in
dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
dom/browser-element/mochitest/browserElement_TargetBlank.js
dom/ipc/TabParent.cpp
xpfe/appshell/src/nsContentTreeOwner.cpp
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -22,16 +22,17 @@
 #include "nsCxPusher.h"
 #include "GeneratedEventClasses.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace {
 
+using mozilla::BrowserElementParent;
 /**
  * Create an <iframe mozbrowser> owned by the same document as
  * aOpenerFrameElement.
  */
 already_AddRefed<HTMLIFrameElement>
 CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
 {
   nsNodeInfoManager *nodeInfoManager =
@@ -67,17 +68,18 @@ CreateIframe(Element* aOpenerFrameElemen
                                        NS_LITERAL_STRING("false"),
                              /* aNotify = */ false);
 
   return popupFrameElement.forget();
 }
 
 bool
 DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
-                       JSContext* cx, JS::Handle<JS::Value> aDetailValue)
+                       JSContext* cx, JS::Handle<JS::Value> aDetailValue,
+                       nsEventStatus *aStatus)
 {
   NS_ENSURE_TRUE(aFrameElement, false);
   nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell();
   nsRefPtr<nsPresContext> presContext;
   if (shell) {
     presContext = shell->GetPresContext();
   }
 
@@ -89,39 +91,44 @@ DispatchCustomDOMEvent(Element* aFrameEl
 
   nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
   NS_ENSURE_TRUE(customEvent, false);
   ErrorResult res;
   CustomEvent* event = static_cast<CustomEvent*>(customEvent.get());
   event->InitCustomEvent(cx,
                          aEventName,
                          /* bubbles = */ true,
-                         /* cancelable = */ false,
+                         /* cancelable = */ true,
                          aDetailValue,
                          res);
   if (res.Failed()) {
     return false;
   }
   customEvent->SetTrusted(true);
   // Dispatch the event.
-  nsEventStatus status = nsEventStatus_eIgnore;
+  *aStatus = nsEventStatus_eConsumeNoDefault;
   nsresult rv = nsEventDispatcher::DispatchDOMEvent(aFrameElement, nullptr,
-                                                    domEvent, presContext, &status);
+                                                    domEvent, presContext, aStatus);
   return NS_SUCCEEDED(rv);
 }
 
+} // anonymous namespace
+
+namespace mozilla {
+
 /**
  * Dispatch a mozbrowseropenwindow event to the given opener frame element.
  * The "popup iframe" (event.detail.frameElement) will be |aPopupFrameElement|.
  *
  * Returns true iff there were no unexpected failures and the window.open call
  * was accepted by the embedder.
  */
-bool
-DispatchOpenWindowEvent(Element* aOpenerFrameElement,
+/*static*/
+BrowserElementParent::OpenWindowResult
+BrowserElementParent::DispatchOpenWindowEvent(Element* aOpenerFrameElement,
                         Element* aPopupFrameElement,
                         const nsAString& aURL,
                         const nsAString& aName,
                         const nsAString& aFeatures)
 {
   // Dispatch a CustomEvent at aOpenerFrameElement with a detail object
   // (OpenWindowEventDetail) containing aPopupFrameElement, aURL, aName, and
   // aFeatures.
@@ -133,83 +140,91 @@ DispatchOpenWindowEvent(Element* aOpener
   detail.mFeatures = aFeatures;
   detail.mFrameElement = aPopupFrameElement;
 
   AutoJSContext cx;
   JS::Rooted<JS::Value> val(cx);
 
   nsIGlobalObject* sgo = aPopupFrameElement->OwnerDoc()->GetScopeObject();
   if (!sgo) {
-    return false;
+    return BrowserElementParent::OPEN_WINDOW_IGNORED;
   }
 
   JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
   JSAutoCompartment ac(cx, global);
   if (!detail.ToObject(cx, global, &val)) {
     MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
-    return false;
+    return BrowserElementParent::OPEN_WINDOW_IGNORED;
   }
 
+  nsEventStatus status;
   bool dispatchSucceeded =
     DispatchCustomDOMEvent(aOpenerFrameElement,
                            NS_LITERAL_STRING("mozbrowseropenwindow"),
                            cx,
-                           val);
+                           val, &status);
 
-  // If the iframe is not in some document's DOM at this point, the embedder
-  // has "blocked" the popup.
-  return (dispatchSucceeded && aPopupFrameElement->IsInDoc());
+  if (dispatchSucceeded) {
+    if (aPopupFrameElement->IsInDoc()) {
+      return BrowserElementParent::OPEN_WINDOW_ADDED;
+    } else if (status == nsEventStatus_eConsumeNoDefault) {
+      // If the frame was not added to a document, report to callers whether
+      // preventDefault was called on or not
+      return BrowserElementParent::OPEN_WINDOW_CANCELLED;
+    }
+  }
+
+  return BrowserElementParent::OPEN_WINDOW_IGNORED;
 }
 
-} // anonymous namespace
-
-namespace mozilla {
-
-/*static*/ bool
+/*static*/
+BrowserElementParent::OpenWindowResult
 BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent,
                                     TabParent* aPopupTabParent,
                                     const nsAString& aURL,
                                     const nsAString& aName,
                                     const nsAString& aFeatures)
 {
   // Create an iframe owned by the same document which owns openerFrameElement.
   nsCOMPtr<Element> openerFrameElement = aOpenerTabParent->GetOwnerElement();
-  NS_ENSURE_TRUE(openerFrameElement, false);
+  NS_ENSURE_TRUE(openerFrameElement,
+                 BrowserElementParent::OPEN_WINDOW_IGNORED);
   nsRefPtr<HTMLIFrameElement> popupFrameElement =
     CreateIframe(openerFrameElement, aName, /* aRemote = */ true);
 
   // Normally an <iframe> element will try to create a frameLoader when the
   // page touches iframe.contentWindow or sets iframe.src.
   //
   // But in our case, we want to delay the creation of the frameLoader until
   // we've verified that the popup has gone through successfully.  If the popup
   // is "blocked" by the embedder, we don't want to load the popup's url.
   //
   // Therefore we call DisallowCreateFrameLoader() on the element and call
   // AllowCreateFrameLoader() only after we've verified that the popup was
   // allowed.
   popupFrameElement->DisallowCreateFrameLoader();
 
-  bool dispatchSucceeded =
+  OpenWindowResult opened =
     DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
                             aURL, aName, aFeatures);
-  if (!dispatchSucceeded) {
-    return false;
+
+  if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) {
+    return opened;
   }
 
   // The popup was not blocked, so hook up the frame element and the popup tab
   // parent, and return success.
   aPopupTabParent->SetOwnerElement(popupFrameElement);
   popupFrameElement->AllowCreateFrameLoader();
   popupFrameElement->CreateRemoteFrameLoader(aPopupTabParent);
-
-  return true;
+  return opened;
 }
 
-/* static */ bool
+/* static */
+BrowserElementParent::OpenWindowResult
 BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
                                           nsIURI* aURI,
                                           const nsAString& aName,
                                           const nsACString& aFeatures,
                                           nsIDOMWindow** aReturnWindow)
 {
   *aReturnWindow = NULL;
 
@@ -221,50 +236,53 @@ BrowserElementParent::OpenWindowInProces
   // GetScriptableTop gets us the <iframe mozbrowser>'s window; we'll use its
   // frame element, rather than aOpenerWindow's frame element, as our "opener
   // frame element" below.
   nsCOMPtr<nsIDOMWindow> topWindow;
   aOpenerWindow->GetScriptableTop(getter_AddRefs(topWindow));
 
   nsCOMPtr<nsIDOMElement> openerFrameDOMElement;
   topWindow->GetFrameElement(getter_AddRefs(openerFrameDOMElement));
-  NS_ENSURE_TRUE(openerFrameDOMElement, false);
+  NS_ENSURE_TRUE(openerFrameDOMElement, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   nsCOMPtr<Element> openerFrameElement =
     do_QueryInterface(openerFrameDOMElement);
 
   nsRefPtr<HTMLIFrameElement> popupFrameElement =
     CreateIframe(openerFrameElement, aName, /* aRemote = */ false);
-  NS_ENSURE_TRUE(popupFrameElement, false);
+  NS_ENSURE_TRUE(popupFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   nsAutoCString spec;
   if (aURI) {
     aURI->GetSpec(spec);
   }
-  bool dispatchSucceeded =
+
+  OpenWindowResult opened =
     DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
                             NS_ConvertUTF8toUTF16(spec),
                             aName,
                             NS_ConvertUTF8toUTF16(aFeatures));
-  if (!dispatchSucceeded) {
-    return false;
+
+  if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) {
+    return opened;
   }
 
   // Return popupFrameElement's window.
   nsCOMPtr<nsIFrameLoader> frameLoader;
   popupFrameElement->GetFrameLoader(getter_AddRefs(frameLoader));
-  NS_ENSURE_TRUE(frameLoader, false);
+  NS_ENSURE_TRUE(frameLoader, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   nsCOMPtr<nsIDocShell> docshell;
   frameLoader->GetDocShell(getter_AddRefs(docshell));
-  NS_ENSURE_TRUE(docshell, false);
+  NS_ENSURE_TRUE(docshell, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docshell);
   window.forget(aReturnWindow);
-  return !!*aReturnWindow;
+
+  return !!*aReturnWindow ? opened : BrowserElementParent::OPEN_WINDOW_CANCELLED;
 }
 
 class DispatchAsyncScrollEventRunnable : public nsRunnable
 {
 public:
   DispatchAsyncScrollEventRunnable(TabParent* aTabParent,
                                    const CSSRect& aContentRect,
                                    const CSSSize& aContentSize)
@@ -297,20 +315,21 @@ NS_IMETHODIMP DispatchAsyncScrollEventRu
 
   // We can get away with a null global here because
   // AsyncScrollEventDetail only contains numeric values.
   if (!detail.ToObject(cx, JS::NullPtr(), &val)) {
     MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
     return NS_ERROR_FAILURE;
   }
 
+  nsEventStatus status = nsEventStatus_eIgnore;
   DispatchCustomDOMEvent(frameElement,
                          NS_LITERAL_STRING("mozbrowserasyncscroll"),
                          cx,
-                         val);
+                         val, &status);
   return NS_OK;
 }
 
 bool
 BrowserElementParent::DispatchAsyncScrollEvent(TabParent* aTabParent,
                                                const CSSRect& aContentRect,
                                                const CSSSize& aContentSize)
 {
--- a/dom/browser-element/BrowserElementParent.h
+++ b/dom/browser-element/BrowserElementParent.h
@@ -4,16 +4,17 @@
 
 #ifndef mozilla_BrowserElementHelpers_h
 #define mozilla_BrowserElementHelpers_h
 
 #include "nsAString.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/gfx/Rect.h"
 #include "Units.h"
+#include "mozilla/dom/Element.h"
 
 class nsIDOMWindow;
 class nsIURI;
 
 namespace mozilla {
 
 namespace dom {
 class TabParent;
@@ -28,16 +29,32 @@ class TabParent;
  * functionality which must be written in C++.
  *
  * We don't communicate with the JS code that lives in BrowserElementParent.js;
  * the JS and C++ parts are completely separate.
  */
 class BrowserElementParent
 {
 public:
+
+  /**
+   * Possible results from a window.open call.
+   * ADDED     - The frame was added to a document (i.e. handled by the embedder).
+   * IGNORED   - The frame was not added to a document and the embedder didn't
+   *             call preventDefault() to prevent the platform from handling the call.
+   * CANCELLED - The frame was not added to a document, but the embedder still
+   *             called preventDefault() to prevent the platform from handling the call.
+   */
+
+  enum OpenWindowResult {
+    OPEN_WINDOW_ADDED,
+    OPEN_WINDOW_IGNORED,
+    OPEN_WINDOW_CANCELLED
+  };
+
   /**
    * Handle a window.open call from an out-of-process <iframe mozbrowser>.
    *
    * window.open inside <iframe mozbrowser> doesn't actually open a new
    * top-level window.  Instead, the "embedder" (the document which contains
    * the <iframe mozbrowser> whose content called window.open) gets the
    * opportunity to place a new <iframe mozbrowser> in the DOM somewhere.  This
    * new "popup" iframe acts as the opened window.
@@ -56,39 +73,39 @@ public:
    *    set aPopupTabParent's frame element to event.detail.frameElement.
    *    Otherwise, we return false.
    *
    * @param aURL the URL the new window should load.  The empty string is
    *             allowed.
    * @param aOpenerTabParent the TabParent whose TabChild called window.open.
    * @param aPopupTabParent the TabParent inside which the opened window will
    *                        live.
-   * @return true on success, false otherwise.  Failure is not (necessarily)
-   *         an error; it may indicate that the embedder simply rejected the
-   *         window.open request.
+   * @return an OpenWindowresult that describes whether the embedder added the
+   *         frame to a document and whether it called preventDefault to prevent
+   *         the platform from handling the open request.
    */
-  static bool
+  static OpenWindowResult
   OpenWindowOOP(dom::TabParent* aOpenerTabParent,
                 dom::TabParent* aPopupTabParent,
                 const nsAString& aURL,
                 const nsAString& aName,
                 const nsAString& aFeatures);
 
   /**
    * Handle a window.open call from an in-process <iframe mozbrowser>.
    *
-   * As with OpenWindowOOP, we return true if the window.open request
-   * succeeded, and return false if the embedder denied the request.
-   *
    * (These parameter types are silly, but they match what our caller has in
    * hand.  Feel free to add an override, if they are inconvenient to you.)
    *
    * @param aURI the URI the new window should load.  May be null.
+   * @return an OpenWindowResult that describes whether the browser added the
+   *         frame to a document or whether they called preventDefault to prevent
+   *         the platform from handling the open request
    */
-  static bool
+  static OpenWindowResult
   OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
                       nsIURI* aURI,
                       const nsAString& aName,
                       const nsACString& aFeatures,
                       nsIDOMWindow** aReturnWindow);
 
   /**
    * Fire a mozbrowserasyncscroll CustomEvent on the given TabParent's frame element.
@@ -104,13 +121,21 @@ public:
    * page "rubber-bands" after being scrolled all the way to the bottom.
    * Similarly, aContentRect.left + aContentRect.width may be greater than
    * contentSize.width, and both left and top may be negative.
    */
   static bool
   DispatchAsyncScrollEvent(dom::TabParent* aTabParent,
                            const CSSRect& aContentRect,
                            const CSSSize& aContentSize);
+
+private:
+  static OpenWindowResult
+  DispatchOpenWindowEvent(dom::Element* aOpenerFrameElement,
+                          dom::Element* aPopupFrameElement,
+                          const nsAString& aURL,
+                          const nsAString& aName,
+                          const nsAString& aFeatures);
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/browser-element/Makefile.in
+++ b/dom/browser-element/Makefile.in
@@ -5,11 +5,12 @@
 include $(topsrcdir)/dom/dom-config.mk
 
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 INCLUDES	+= \
 		-I$(topsrcdir)/dom/base \
+		-I$(topsrcdir)/dom/ \
 		-I$(topsrcdir)/dom/ipc \
 		-I$(topsrcdir)/content/base/src \
 		$(NULL)
--- a/dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
+++ b/dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
@@ -27,16 +27,19 @@ function runTest() {
     SimpleTest.executeSoon(function() {
       var iframe2 = document.createElement('iframe');
       SpecialPowers.wrap(iframe2).mozbrowser = true;
       iframe2.setAttribute('mozapp', 'http://example.com/manifest.webapp');
 
       iframe2.addEventListener('mozbrowseropenwindow', function(e) {
         ok(true, "Got second mozbrowseropenwindow event.");
         SpecialPowers.removePermission("embed-apps", document);
+
+        // We're not going to open this, but we don't want the platform to either
+        e.preventDefault();
         SimpleTest.finish();
       });
 
       document.body.appendChild(iframe2);
       iframe2.src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_AppWindowNamespace.html';
     });
   });
 
--- a/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
@@ -16,16 +16,17 @@ function runTest() {
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(e.detail.url.indexOf('does_not_exist.html') != -1,
        'Opened URL; got ' + e.detail.url);
     is(e.detail.name, '');
     is(e.detail.features, '');
 
     // Don't add e.detail.frameElement to the DOM, so the window.open is
     // effectively blocked.
+    e.preventDefault();
   });
 
   iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
     var msg = e.detail.message;
     if (msg.indexOf('success:') == 0) {
       ok(true, msg);
     }
     else if (msg == 'finish') {
--- a/dom/browser-element/mochitest/browserElement_TargetBlank.js
+++ b/dom/browser-element/mochitest/browserElement_TargetBlank.js
@@ -10,16 +10,17 @@ browserElementTestHelpers.setEnabledPref
 browserElementTestHelpers.addPermission();
 
 function runTest() {
   var iframe = document.createElement('iframe');
   SpecialPowers.wrap(iframe).mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     is(e.detail.url, 'http://example.com/');
+    e.preventDefault();
     SimpleTest.finish();
   });
 
   iframe.src = "file_browserElement_TargetBlank.html";
   document.body.appendChild(iframe);
 }
 
 addEventListener('testready', runTest);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1519,19 +1519,20 @@ TabParent::MaybeForwardEventToRenderFram
 
 bool
 TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                       const nsString& aURL,
                                       const nsString& aName,
                                       const nsString& aFeatures,
                                       bool* aOutWindowOpened)
 {
-  *aOutWindowOpened =
+  BrowserElementParent::OpenWindowResult opened =
     BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
                                         this, aURL, aName, aFeatures);
+  *aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED);
   return true;
 }
 
 bool
 TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor,
                                        ScrollingBehavior* scrolling,
                                        TextureFactoryIdentifier* factoryIdentifier,
                                        uint64_t* layersId)
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -26,16 +26,19 @@
 #include "nsIPrompt.h"
 #include "nsIAuthPrompt.h"
 #include "nsIWindowMediator.h"
 #include "nsIXULBrowserWindow.h"
 #include "nsIPrincipal.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIWebNavigation.h"
+#include "nsDocShellCID.h"
+#include "nsIExternalURLHandlerService.h"
+#include "nsIMIMEInfo.h"
 #include "mozilla/BrowserElementParent.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
 #endif
@@ -827,24 +830,46 @@ nsContentTreeOwner::ProvideWindow(nsIDOM
   // If aParent is inside an <iframe mozbrowser> and this isn't a request to
   // open a modal-type window, we're going to create a new <iframe mozbrowser>
   // and return its window here.
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
   if (docshell && docshell->GetIsInBrowserOrApp() &&
       !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
                         nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
                         nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
-    *aWindowIsNew =
+
+    BrowserElementParent::OpenWindowResult opened =
       BrowserElementParent::OpenWindowInProcess(aParent, aURI, aName,
                                                 aFeatures, aReturn);
 
-    // If OpenWindowInProcess failed (perhaps because the embedder blocked the
+    // If OpenWindowInProcess handled the open (by opening it or blocking the
     // popup), tell our caller not to proceed trying to create a new window
     // through other means.
-    return *aWindowIsNew ? NS_OK : NS_ERROR_ABORT;
+    if (opened != BrowserElementParent::OPEN_WINDOW_IGNORED) {
+      *aWindowIsNew = opened == BrowserElementParent::OPEN_WINDOW_ADDED;
+      return *aWindowIsNew ? NS_OK : NS_ERROR_ABORT;
+    }
+
+    // If we're in an app and the target is _blank, send the url to the OS
+    if (aName.LowerCaseEqualsLiteral("_blank")) {
+      nsCOMPtr<nsIExternalURLHandlerService> exUrlServ(
+                        do_GetService(NS_EXTERNALURLHANDLERSERVICE_CONTRACTID));
+      if (exUrlServ) {
+
+        nsCOMPtr<nsIHandlerInfo> info;
+        bool found;
+        exUrlServ->GetURLHandlerInfoFromOS(aURI, &found, getter_AddRefs(info));
+  
+        if (info && found) {
+          info->LaunchWithURI(aURI, nullptr);
+          return NS_ERROR_ABORT;
+        }
+
+      }
+    }
   }
 
   // the parent window is fullscreen mode or not.
   bool isFullScreen = false;
   if (aParent) {
     aParent->GetFullScreen(&isFullScreen);
   }