Bug 1477610 - Flush layout when reporting the visual viewport size via the Visual Viewport API. r=hiro
authorBotond Ballo <botond@mozilla.com>
Thu, 09 May 2019 03:56:41 +0000
changeset 531984 6f7cd5ebb041ea3c4de4206d5489883e239ffbb5
parent 531983 3390fa47ebcd66eadead3c8bfe75d61f52c6812a
child 531985 ca147aeec45e24d7e614846461228261d1439ca4
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1477610
milestone68.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 1477610 - Flush layout when reporting the visual viewport size via the Visual Viewport API. r=hiro Differential Revision: https://phabricator.services.mozilla.com/D29089
dom/base/VisualViewport.cpp
dom/base/VisualViewport.h
testing/web-platform/meta/visual-viewport/viewport-read-size-causes-layout.html.ini
testing/web-platform/meta/visual-viewport/viewport-read-size-in-iframe-causes-layout.html.ini
testing/web-platform/meta/visual-viewport/viewport-scrollbars-cause-resize.html.ini
testing/web-platform/meta/visual-viewport/viewport-unscaled-size.html.ini
--- a/dom/base/VisualViewport.cpp
+++ b/dom/base/VisualViewport.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/ToString.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
 #include "nsPresContext.h"
 #include "nsRefreshDriver.h"
+#include "DocumentInlines.h"
 
 #define VVP_LOG(...)
 // #define VVP_LOG(...) printf_stderr("VVP: " __VA_ARGS__)
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 VisualViewport::VisualViewport(nsPIDOMWindowInner* aWindow)
@@ -55,16 +56,24 @@ void VisualViewport::GetEventTargetParen
     }
   }
   aVisitor.SetParentTarget(parentTarget, false);
 }
 
 CSSSize VisualViewport::VisualViewportSize() const {
   CSSSize size = CSSSize(0, 0);
 
+  // Flush layout, as that may affect the answer below (e.g. scrollbars
+  // may have appeared, decreasing the available viewport size).
+  RefPtr<const VisualViewport> kungFuDeathGrip(this);
+  if (Document* doc = GetDocument()) {
+    doc->FlushPendingNotifications(FlushType::Layout);
+  }
+
+  // Fetch the pres shell after the layout flush, as it might have destroyed it.
   if (PresShell* presShell = GetPresShell()) {
     if (presShell->IsVisualViewportSizeSet()) {
       size = CSSRect::FromAppUnits(presShell->GetVisualViewportSize());
     } else {
       nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
       if (sf) {
         size = CSSRect::FromAppUnits(sf->GetScrollPortRect().Size());
       }
@@ -116,37 +125,38 @@ double VisualViewport::PageTop() const {
 double VisualViewport::OffsetLeft() const {
   return PageLeft() - LayoutViewportOffset().X();
 }
 
 double VisualViewport::OffsetTop() const {
   return PageTop() - LayoutViewportOffset().Y();
 }
 
-PresShell* VisualViewport::GetPresShell() const {
+Document* VisualViewport::GetDocument() const {
   nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
   if (!window) {
     return nullptr;
   }
 
   nsIDocShell* docShell = window->GetDocShell();
   if (!docShell) {
     return nullptr;
   }
 
-  return docShell->GetPresShell();
+  return docShell->GetDocument();
+}
+
+PresShell* VisualViewport::GetPresShell() const {
+  RefPtr<Document> document = GetDocument();
+  return document ? document->GetPresShell() : nullptr;
 }
 
 nsPresContext* VisualViewport::GetPresContext() const {
-  PresShell* presShell = GetPresShell();
-  if (!presShell) {
-    return nullptr;
-  }
-
-  return presShell->GetPresContext();
+  RefPtr<Document> document = GetDocument();
+  return document ? document->GetPresContext() : nullptr;
 }
 
 /* ================= Resize event handling ================= */
 
 void VisualViewport::PostResizeEvent() {
   VVP_LOG("%p: PostResizeEvent (pre-existing: %d)\n", this, !!mResizeEvent);
   nsPresContext* presContext = GetPresContext();
   if (mResizeEvent && mResizeEvent->HasPresContext(presContext)) {
--- a/dom/base/VisualViewport.h
+++ b/dom/base/VisualViewport.h
@@ -23,18 +23,18 @@ namespace dom {
 class VisualViewport final : public mozilla::DOMEventTargetHelper {
  public:
   explicit VisualViewport(nsPIDOMWindowInner* aWindow);
 
   double OffsetLeft() const;
   double OffsetTop() const;
   double PageLeft() const;
   double PageTop() const;
-  double Width() const;
-  double Height() const;
+  MOZ_CAN_RUN_SCRIPT double Width() const;
+  MOZ_CAN_RUN_SCRIPT double Height() const;
   double Scale() const;
   IMPL_EVENT_HANDLER(resize)
   IMPL_EVENT_HANDLER(scroll)
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
 
@@ -83,19 +83,20 @@ class VisualViewport final : public mozi
     // in fact change or not.
     const nsPoint mPrevVisualOffset;
     const nsPoint mPrevLayoutOffset;
   };
 
  private:
   virtual ~VisualViewport();
 
-  CSSSize VisualViewportSize() const;
+  MOZ_CAN_RUN_SCRIPT CSSSize VisualViewportSize() const;
   CSSPoint VisualViewportOffset() const;
   CSSPoint LayoutViewportOffset() const;
+  Document* GetDocument() const;
   PresShell* GetPresShell() const;
   nsPresContext* GetPresContext() const;
 
   void FireResizeEvent();
   void FireScrollEvent();
 
   RefPtr<VisualViewportResizeEvent> mResizeEvent;
   RefPtr<VisualViewportScrollEvent> mScrollEvent;
deleted file mode 100644
--- a/testing/web-platform/meta/visual-viewport/viewport-read-size-causes-layout.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[viewport-read-size-causes-layout.html]
-  [Untitled]
-    expected: FAIL
-
-  [viewport-read-size-causes-layout]
-    expected:
-      if (os == "android") and not e10s: PASS
-      if (os == "android") and e10s: PASS
-      FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/visual-viewport/viewport-read-size-in-iframe-causes-layout.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[viewport-read-size-in-iframe-causes-layout.html]
-  [Untitled]
-    expected: FAIL
-
-  [viewport-read-size-in-iframe-causes-layout]
-    expected:
-      if (os == "android") and not e10s: PASS
-      if (os == "android") and e10s: PASS
-      FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/visual-viewport/viewport-scrollbars-cause-resize.html.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[viewport-scrollbars-cause-resize.html]
-  [Viewport: Scrollbars Cause Resize]
-    expected:
-      if (os == "android") and not e10s: PASS
-      FAIL
-
-  [view size reflects appearance of classic scrollbars]
-    expected:
-      if (os == "android") and not e10s: PASS
-      if (os == "android") and e10s: PASS
-      FAIL
-
-  [Resize event was fired at window.visualViewport if, and only if, scrollbars are classic (i.e. affect flow)]
-    disabled: Bug 1515043
-
deleted file mode 100644
--- a/testing/web-platform/meta/visual-viewport/viewport-unscaled-size.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[viewport-unscaled-size.html]
-  [visualViewport.width should exclude scrollbar.]
-    expected:
-      if (os == "android") and not e10s: PASS
-      if (os == "android") and e10s: PASS
-      FAIL
-