Bug 1036606 - Extend mozRequestFullScreen to accept an options dict with a vrDisplay member; r=bz
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 09 Jul 2014 12:30:22 -0700
changeset 241253 135200e5405deca6a4fbc70a1b4c79ebdaf755bb
parent 241252 66f63e8af1ca79a759d70ae756da3571e977398c
child 241254 c080f66ed9d2ed0515677c99828310434ec18ecd
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1036606
milestone36.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 1036606 - Extend mozRequestFullScreen to accept an options dict with a vrDisplay member; r=bz
dom/base/Element.cpp
dom/base/Element.h
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIDocument.h
dom/base/nsPIDOMWindow.h
dom/webidl/Element.webidl
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -133,16 +133,17 @@
 #include "nsXBLService.h"
 #include "nsITextControlElement.h"
 #include "nsITextControlFrame.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/ElementBinding.h"
+#include "mozilla/dom/VRDevice.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsIAtom*
 nsIContent::DoGetID() const
 {
   MOZ_ASSERT(HasID(), "Unexpected call");
@@ -3068,17 +3069,17 @@ GetFullScreenError(nsIDocument* aDoc)
   if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) {
     return "FullScreenDeniedBlocked";
   }
 
   return nullptr;
 }
 
 void
-Element::MozRequestFullScreen()
+Element::MozRequestFullScreen(const RequestFullscreenOptions& aOptions)
 {
   // 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.
   // Note that requests for fullscreen inside a web app's origin are exempt
   // from this restriction.
@@ -3092,17 +3093,22 @@ Element::MozRequestFullScreen()
       new AsyncEventDispatcher(OwnerDoc(),
                                NS_LITERAL_STRING("mozfullscreenerror"),
                                true,
                                false);
     asyncDispatcher->PostDOMEvent();
     return;
   }
 
-  OwnerDoc()->AsyncRequestFullScreen(this);
+  FullScreenOptions opts;
+  if (aOptions.mVrDisplay) {
+    opts.mVRHMDDevice = aOptions.mVrDisplay->GetHMD();
+  }
+
+  OwnerDoc()->AsyncRequestFullScreen(this, opts);
 
   return;
 }
 
 void
 Element::MozRequestPointerLock()
 {
   OwnerDoc()->RequestPointerLock(this);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -29,16 +29,17 @@
 #include "nsIScrollableFrame.h"
 #include "mozilla/dom/Attr.h"
 #include "nsISMILAttr.h"
 #include "mozilla/dom/DOMRect.h"
 #include "nsAttrValue.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/WindowBinding.h"
+#include "mozilla/dom/ElementBinding.h"
 #include "Units.h"
 
 class nsIDOMEventListener;
 class nsIFrame;
 class nsIDOMMozNamedAttrMap;
 class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsIControllers;
@@ -719,17 +720,17 @@ public:
     }
   }
   void ReleaseCapture()
   {
     if (nsIPresShell::GetCapturingContent() == this) {
       nsIPresShell::SetCapturingContent(nullptr, 0);
     }
   }
-  void MozRequestFullScreen();
+  void MozRequestFullScreen(const RequestFullscreenOptions& aOptions);
   void MozRequestPointerLock();
   Attr* GetAttributeNode(const nsAString& aName);
   already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
                                           ErrorResult& aError);
   already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
                                              ErrorResult& aError);
   Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName);
@@ -1763,17 +1764,17 @@ NS_IMETHOD SetCapture(bool retargetToEle
 }                                                                             \
 NS_IMETHOD ReleaseCapture(void) MOZ_FINAL                                     \
 {                                                                             \
   Element::ReleaseCapture();                                                  \
   return NS_OK;                                                               \
 }                                                                             \
 NS_IMETHOD MozRequestFullScreen(void) MOZ_FINAL                               \
 {                                                                             \
-  Element::MozRequestFullScreen();                                            \
+  Element::MozRequestFullScreen(mozilla::dom::RequestFullscreenOptions());    \
   return NS_OK;                                                               \
 }                                                                             \
 NS_IMETHOD MozRequestPointerLock(void) MOZ_FINAL                              \
 {                                                                             \
   Element::MozRequestPointerLock();                                           \
   return NS_OK;                                                               \
 }                                                                             \
 using nsINode::QuerySelector;                                                 \
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10725,30 +10725,31 @@ nsIDocument::MozCancelFullScreen()
 
 // Runnable to set window full-screen mode. Used as a script runner
 // to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to
 // run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
 // (handled in chome code) which is unsafe to run if this is called in
 // Element::UnbindFromTree().
 class nsSetWindowFullScreen : public nsRunnable {
 public:
-  nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue)
-    : mDoc(aDoc), mValue(aValue) {}
+  nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo* aHMD = nullptr)
+    : mDoc(aDoc), mValue(aValue), mHMD(aHMD) {}
 
   NS_IMETHOD Run()
   {
     if (mDoc->GetWindow()) {
-      mDoc->GetWindow()->SetFullScreenInternal(mValue, false);
+      mDoc->GetWindow()->SetFullScreenInternal(mValue, false, mHMD);
     }
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIDocument> mDoc;
   bool mValue;
+  nsRefPtr<gfx::VRHMDInfo> mHMD;
 };
 
 static nsIDocument*
 GetFullscreenRootDocument(nsIDocument* aDoc)
 {
   if (!aDoc) {
     return nullptr;
   }
@@ -10758,27 +10759,27 @@ GetFullscreenRootDocument(nsIDocument* a
          (!nsContentUtils::IsFullscreenApiContentOnly() ||
           !nsContentUtils::IsChromeDoc(parent))) {
     doc = parent;
   }
   return doc;
 }
 
 static void
-SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
+SetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo *aVRHMD = nullptr)
 {
   // Maintain list of fullscreen root documents.
   nsCOMPtr<nsIDocument> root = GetFullscreenRootDocument(aDoc);
   if (aValue) {
     FullscreenRoots::Add(root);
   } else {
     FullscreenRoots::Remove(root);
   }
   if (!nsContentUtils::IsFullscreenApiContentOnly()) {
-    nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
+    nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue, aVRHMD));
   }
 }
 
 class nsCallExitFullscreen : public nsRunnable {
 public:
   explicit nsCallExitFullscreen(nsIDocument* aDoc)
     : mDoc(aDoc) {}
   NS_IMETHOD Run()
@@ -11088,54 +11089,58 @@ bool
 nsDocument::IsFullScreenDoc()
 {
   return GetFullScreenElement() != nullptr;
 }
 
 class nsCallRequestFullScreen : public nsRunnable
 {
 public:
-  explicit nsCallRequestFullScreen(Element* aElement)
+  explicit nsCallRequestFullScreen(Element* aElement, FullScreenOptions& aOptions)
     : mElement(aElement),
       mDoc(aElement->OwnerDoc()),
       mWasCallerChrome(nsContentUtils::IsCallerChrome()),
       mHadRequestPending(static_cast<nsDocument*>(mDoc.get())->
-                           mAsyncFullscreenPending)
+                         mAsyncFullscreenPending),
+      mOptions(aOptions)
   {
     static_cast<nsDocument*>(mDoc.get())->
       mAsyncFullscreenPending = true;
   }
 
   NS_IMETHOD Run()
   {
     static_cast<nsDocument*>(mDoc.get())->
       mAsyncFullscreenPending = mHadRequestPending;
     nsDocument* doc = static_cast<nsDocument*>(mDoc.get());
     doc->RequestFullScreen(mElement,
+                           mOptions,
                            mWasCallerChrome,
                            /* aNotifyOnOriginChange */ true);
     return NS_OK;
   }
 
   nsRefPtr<Element> mElement;
   nsCOMPtr<nsIDocument> mDoc;
   bool mWasCallerChrome;
   bool mHadRequestPending;
+  FullScreenOptions mOptions;
 };
 
 void
-nsDocument::AsyncRequestFullScreen(Element* aElement)
+nsDocument::AsyncRequestFullScreen(Element* aElement,
+                                   FullScreenOptions& aOptions)
 {
   NS_ASSERTION(aElement,
     "Must pass non-null element to nsDocument::AsyncRequestFullScreen");
   if (!aElement) {
     return;
   }
   // Request full-screen asynchronously.
-  nsCOMPtr<nsIRunnable> event(new nsCallRequestFullScreen(aElement));
+  nsCOMPtr<nsIRunnable> event(new nsCallRequestFullScreen(aElement, aOptions));
   NS_DispatchToCurrentThread(event);
 }
 
 static void
 LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
 {
   if (!aLogFailure) {
     return;
@@ -11193,16 +11198,19 @@ nsDocument::CleanupFullscreenState()
 {
   if (!mFullScreenStack.IsEmpty()) {
     // The top element in the full-screen stack will have full-screen
     // style bits set on it and its ancestors. Remove the style bits.
     // Note the non-top elements won't have the style bits set.
     Element* top = FullScreenStackTop();
     NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty");
     if (top) {
+      // Remove any VR state properties
+      top->DeleteProperty(nsGkAtoms::vr_state);
+
       EventStateManager::SetFullScreenState(top, false);
     }
     mFullScreenStack.Clear();
   }
   SetApprovedForFullscreen(false);
   RemoveFullscreenApprovedObserver();
   mFullscreenRoot = nullptr;
 }
@@ -11229,18 +11237,22 @@ nsDocument::FullScreenStackPush(Element*
 
 void
 nsDocument::FullScreenStackPop()
 {
   if (mFullScreenStack.IsEmpty()) {
     return;
   }
 
+  Element* top = FullScreenStackTop();
+
+  // Remove any VR state properties
+  top->DeleteProperty(nsGkAtoms::vr_state);
+
   // Remove styles from existing top element.
-  Element* top = FullScreenStackTop();
   EventStateManager::SetFullScreenState(top, false);
 
   // Remove top element. Note the remaining top element in the stack
   // will not have full-screen style bits set, so we will need to restore
   // them on the new top element before returning.
   uint32_t last = mFullScreenStack.Length() - 1;
   mFullScreenStack.RemoveElementAt(last);
 
@@ -11318,17 +11330,19 @@ IsInActiveTab(nsIDocument* aDoc)
 
 nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
                                                   const nsAString& aOrigin)
 {
   // Ensure the frame element is the fullscreen element in this document.
   // If the frame element is already the fullscreen element in this document,
   // this has no effect.
   nsCOMPtr<nsIContent> content(do_QueryInterface(aFrameElement));
+  FullScreenOptions opts;
   RequestFullScreen(content->AsElement(),
+                    opts,
                     /* aWasCallerChrome */ false,
                     /* aNotifyOnOriginChange */ false);
 
   // Origin changed in child process, send notifiction, so that chrome can
   // update the UI to reflect the fullscreen origin change if necessary.
   // The BrowserElementChild listens on this, and forwards it over its
   // parent process, where it is redispatched. Chrome (in the root process,
   // which could be *this* process) listens for this notification so that
@@ -11344,18 +11358,27 @@ nsresult nsDocument::RemoteFrameFullscre
 }
 
 nsresult nsDocument::RemoteFrameFullscreenReverted()
 {
   RestorePreviousFullScreenState();
   return NS_OK;
 }
 
+static void
+ReleaseHMDInfoRef(void *, nsIAtom*, void *aPropertyValue, void *)
+{
+  if (aPropertyValue) {
+    static_cast<gfx::VRHMDInfo*>(aPropertyValue)->Release();
+  }
+}
+
 void
 nsDocument::RequestFullScreen(Element* aElement,
+                              FullScreenOptions& aOptions,
                               bool aWasCallerChrome,
                               bool aNotifyOnOriginChange)
 {
   NS_ASSERTION(aElement,
     "Must pass non-null element to nsDocument::RequestFullScreen");
   if (!aElement || aElement == GetFullScreenElement()) {
     return;
   }
@@ -11434,16 +11457,24 @@ nsDocument::RequestFullScreen(Element* a
   // If a document is already in fullscreen, then unlock the mouse pointer
   // before setting a new document to fullscreen
   nsCOMPtr<Element> pointerLockedElement =
     do_QueryReferent(EventStateManager::sPointerLockedElement);
   if (pointerLockedElement) {
     UnlockPointer();
   }
 
+  // Process options -- in this case, just HMD
+  if (aOptions.mVRHMDDevice) {
+    nsRefPtr<gfx::VRHMDInfo> hmdRef = aOptions.mVRHMDDevice;
+    aElement->SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
+                          ReleaseHMDInfoRef,
+                          true);
+  }
+
   // Set the full-screen element. This sets the full-screen style on the
   // element, and the full-screen-ancestor styles on ancestors of the element
   // in this document.
   DebugOnly<bool> x = FullScreenStackPush(aElement);
   NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
   changed.AppendElement(this);
 
   // Propagate up the document hierarchy, setting the full-screen element as
@@ -11538,17 +11569,17 @@ nsDocument::RequestFullScreen(Element* a
 
   // Make the window full-screen. Note we must make the state changes above
   // before making the window full-screen, as then the document reports as
   // being in full-screen mode when the chrome "fullscreen" event fires,
   // enabling chrome to distinguish between browser and dom full-screen
   // modes. Also note that nsGlobalWindow::SetFullScreen() (which
   // SetWindowFullScreen() calls) proxies to the root window in its hierarchy,
   // and does not operate on the a per-nsIDOMWindow basis.
-  SetWindowFullScreen(this, true);
+  SetWindowFullScreen(this, true, aOptions.mVRHMDDevice);
 }
 
 NS_IMETHODIMP
 nsDocument::GetMozFullScreenElement(nsIDOMElement **aFullScreenElement)
 {
   ErrorResult rv;
   Element* el = GetMozFullScreenElement(rv);
   if (rv.Failed()) {
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1141,17 +1141,18 @@ public:
   virtual nsresult GetStateObject(nsIVariant** aResult) MOZ_OVERRIDE;
 
   virtual nsDOMNavigationTiming* GetNavigationTiming() const MOZ_OVERRIDE;
   virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) MOZ_OVERRIDE;
 
   virtual Element* FindImageMap(const nsAString& aNormalizedMapName) MOZ_OVERRIDE;
 
   virtual Element* GetFullScreenElement() MOZ_OVERRIDE;
-  virtual void AsyncRequestFullScreen(Element* aElement) MOZ_OVERRIDE;
+  virtual void AsyncRequestFullScreen(Element* aElement,
+                                      mozilla::dom::FullScreenOptions& aOptions) MOZ_OVERRIDE;
   virtual void RestorePreviousFullScreenState() MOZ_OVERRIDE;
   virtual bool IsFullscreenLeaf() MOZ_OVERRIDE;
   virtual bool IsFullScreenDoc() MOZ_OVERRIDE;
   virtual void SetApprovedForFullscreen(bool aIsApproved) MOZ_OVERRIDE;
   virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
                                                 const nsAString& aNewOrigin) MOZ_OVERRIDE;
 
   virtual nsresult RemoteFrameFullscreenReverted() MOZ_OVERRIDE;
@@ -1192,16 +1193,17 @@ public:
   // by chrome code. aNotifyOnOriginChange denotes whether we should send a
   // fullscreen-origin-change notification if requesting fullscreen in this
   // document causes the origin which is fullscreen to change. We may want to
   // *not* send this notification if we're calling RequestFullscreen() as part
   // of a continuation of a request in a subdocument, whereupon the caller will
   // need to send the notification with the origin of the document which
   // originally requested fullscreen, not *this* document's origin.
   void RequestFullScreen(Element* aElement,
+                         mozilla::dom::FullScreenOptions& aOptions,
                          bool aWasCallerChrome,
                          bool aNotifyOnOriginChange);
 
   // Removes all elements from the full-screen stack, removing full-scren
   // styles from the top element in the stack.
   void CleanupFullscreenState();
 
   // Add/remove "fullscreen-approved" observer service notification listener.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5925,17 +5925,17 @@ NS_IMETHODIMP
 nsGlobalWindow::SetFullScreen(bool aFullScreen)
 {
   FORWARD_TO_OUTER(SetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
 
   return SetFullScreenInternal(aFullScreen, true);
 }
 
 nsresult
-nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust)
+nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust, gfx::VRHMDInfo* aHMD)
 {
   MOZ_ASSERT(IsOuterWindow());
 
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Only chrome can change our fullScreen mode, unless we're running in
   // untrusted mode.
   if (aFullScreen == FullScreen() ||
@@ -5947,17 +5947,17 @@ nsGlobalWindow::SetFullScreenInternal(bo
   // via the DocShell tree, and if we are not already the root,
   // call SetFullScreen on that window instead.
   nsCOMPtr<nsIDocShellTreeItem> rootItem;
   mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
   nsCOMPtr<nsPIDOMWindow> window = rootItem ? rootItem->GetWindow() : nullptr;
   if (!window)
     return NS_ERROR_FAILURE;
   if (rootItem != mDocShell)
-    return window->SetFullScreenInternal(aFullScreen, aRequireTrust);
+    return window->SetFullScreenInternal(aFullScreen, aRequireTrust, aHMD);
 
   // make sure we don't try to set full screen on a non-chrome window,
   // which might happen in embedding world
   if (mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome)
     return NS_ERROR_FAILURE;
 
   // If we are already in full screen mode, just return.
   if (mFullScreen == aFullScreen)
@@ -5982,18 +5982,23 @@ nsGlobalWindow::SetFullScreenInternal(bo
   mFullScreen = aFullScreen;
 
   // Sometimes we don't want the top-level widget to actually go fullscreen,
   // for example in the B2G desktop client, we don't want the emulated screen
   // dimensions to appear to increase when entering fullscreen mode; we just
   // want the content to fill the entire client area of the emulator window.
   if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
     nsCOMPtr<nsIWidget> widget = GetMainWidget();
-    if (widget)
-      widget->MakeFullScreen(aFullScreen);
+    if (widget) {
+      nsCOMPtr<nsIScreen> screen;
+      if (aHMD) {
+        screen = aHMD->GetScreen();
+      }
+      widget->MakeFullScreen(aFullScreen, screen);
+    }
   }
 
   if (!mFullScreen) {
     // Force exit from DOM full-screen mode. This is so that if we're in
     // DOM full-screen mode and the user exits full-screen mode with
     // the browser full-screen mode toggle keyboard-shortcut, we'll detect
     // that and leave DOM API full-screen mode too.
     nsIDocument::ExitFullscreen(mDoc, /* async */ false);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -463,17 +463,18 @@ public:
   // Outer windows only.
   virtual bool DispatchCustomEvent(const nsAString& aEventName);
   bool DispatchResizeEvent(const mozilla::CSSIntSize& aSize);
 
   // Inner windows only.
   virtual void RefreshCompartmentPrincipal();
 
   // Outer windows only.
-  virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust);
+  virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust,
+                                         mozilla::gfx::VRHMDInfo *aHMD = nullptr);
   bool FullScreen() const;
 
   // Inner windows only.
   virtual void SetHasGamepadEventListener(bool aHasGamepad = true);
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -22,16 +22,17 @@
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "nsWeakReference.h"
 #include "mozilla/dom/DocumentBinding.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 #include "prclist.h"
+#include "gfxVR.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
@@ -130,16 +131,22 @@ class XPathEvaluator;
 class XPathExpression;
 class XPathNSResolver;
 class XPathResult;
 template<typename> class OwningNonNull;
 template<typename> class Sequence;
 
 template<typename, typename> class CallbackObjectHolder;
 typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
+
+struct FullScreenOptions {
+  FullScreenOptions() { }
+  nsRefPtr<gfx::VRHMDInfo> mVRHMDDevice;
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
 { 0x1f343423, 0x957c, 0x4da3, \
   { 0xaa, 0xa3, 0x07, 0x37, 0x54, 0x3e, 0x79, 0x2a } }
 
 // Enum for requesting a particular type of document when creating a doc
@@ -159,16 +166,17 @@ enum DocumentFlavor {
 
 // Some function forward-declarations
 class nsContentList;
 
 already_AddRefed<nsContentList>
 NS_GetContentList(nsINode* aRootNode,
                   int32_t aMatchNameSpaceId,
                   const nsAString& aTagname);
+
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
 class nsIDocument : public nsINode
 {
   typedef mozilla::dom::GlobalObject GlobalObject;
 public:
@@ -1059,17 +1067,18 @@ public:
    * (if any) is pushed onto the fullscreen element stack, and it can be
    * returned to fullscreen status by calling RestorePreviousFullScreenState().
    *
    * Note that requesting fullscreen in a document also makes the element which
    * contains this document in this document's parent document fullscreen. i.e.
    * the <iframe> or <browser> that contains this document is also mode
    * fullscreen. This happens recursively in all ancestor documents.
    */
-  virtual void AsyncRequestFullScreen(Element* aElement) = 0;
+  virtual void AsyncRequestFullScreen(Element* aElement,
+                                      mozilla::dom::FullScreenOptions& aOptions) = 0;
 
   /**
    * Called when a frame in a child process has entered fullscreen or when a
    * fullscreen frame in a child process changes to another origin.
    * aFrameElement is the frame element which contains the child-process
    * fullscreen document, and aNewOrigin is the origin of the new fullscreen
    * document.
    */
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -33,16 +33,19 @@ class nsPIWindowRoot;
 class nsXBLPrototypeHandler;
 struct nsTimeout;
 
 namespace mozilla {
 namespace dom {
 class AudioContext;
 class Element;
 }
+namespace gfx {
+class VRHMDInfo;
+}
 }
 
 // Popup control state enum. The values in this enum must go from most
 // permissive to least permissive so that it's safe to push state in
 // all situations. Pushing popup state onto the stack never makes the
 // current popup state less permissive (see
 // nsGlobalWindow::PushPopupControlState()).
 enum PopupControlState {
@@ -55,18 +58,18 @@ enum PopupControlState {
 enum UIStateChangeType
 {
   UIStateChangeType_NoChange,
   UIStateChangeType_Set,
   UIStateChangeType_Clear
 };
 
 #define NS_PIDOMWINDOW_IID \
-{ 0x71412748, 0x6368, 0x4332, \
-  { 0x82, 0x66, 0xff, 0xaa, 0x19, 0xda, 0x09, 0x7c } }
+{ 0x19fb3019, 0x7b5d, 0x4235, \
+  { 0xa9, 0x59, 0xa2, 0x31, 0xa2, 0xe7, 0x94, 0x79 } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -455,19 +458,23 @@ public:
     return mMayHaveTouchCaret;
   }
 
   /**
    * Moves the top-level window into fullscreen mode if aIsFullScreen is true,
    * otherwise exits fullscreen. If aRequireTrust is true, this method only
    * changes window state in a context trusted for write.
    *
+   * If aHMD is not null, the window is made full screen on the given VR HMD
+   * device instead of its currrent display.
+   *
    * Outer windows only.
    */
-  virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust) = 0;
+  virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust,
+                                         mozilla::gfx::VRHMDInfo *aHMD = nullptr) = 0;
 
   /**
    * Call this to check whether some node (this window, its document,
    * or content in that document) has a mouseenter/leave event listener.
    */
   bool HasMouseEnterLeaveEventListeners()
   {
     return mMayHaveMouseEnterLeaveEventListener;
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -119,19 +119,21 @@ interface Element : Node {
    */
   void releaseCapture();
 
   // Mozilla extensions
   /**
    * Requests that this element be made the full-screen element, as per the DOM
    * full-screen api.
    *
+   * The fsOptions parameter is non-standard.
+   *
    * @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
    */
-  void mozRequestFullScreen();
+  void mozRequestFullScreen(optional RequestFullscreenOptions fsOptions);
 
   /**
    * Requests that this element be made the pointer-locked element, as per the DOM
    * pointer lock api.
    *
    * @see <http://dvcs.w3.org/hg/pointerlock/raw-file/default/index.html>
    */
   void mozRequestPointerLock();
@@ -230,8 +232,15 @@ partial interface Element {
   readonly attribute ShadowRoot? shadowRoot;
 };
 
 Element implements ChildNode;
 Element implements NonDocumentTypeChildNode;
 Element implements ParentNode;
 Element implements Animatable;
 Element implements GeometryUtils;
+
+// non-standard: allows passing options to Element.requestFullScreen
+dictionary RequestFullscreenOptions {
+  // Which HMDVRDevice to go full screen on; also enables VR rendering.
+  // If null, normal fullscreen is entered.
+  HMDVRDevice? vrDisplay = null;
+};