diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 88e72e76dc35..183ed82ba469 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -161,6 +161,7 @@ #include "nsBlockFrame.h" #include "DOMMatrix.h" +#include "MobileViewportManager.h" #ifdef ACCESSIBILITY # include "nsAccessibilityService.h" @@ -845,13 +846,17 @@ nsRect Element::GetClientAreaRect() { // We will always have a pres shell if we have a pres context, and we will // only get here if we have a pres context from the root content document // check - PresShell* presShell = doc->GetPresShell(); + RefPtr presShell = doc->GetPresShell(); // Ensure up to date dimensions, but don't reflow RefPtr viewManager = presShell->GetViewManager(); if (viewManager) { viewManager->FlushDelayedResize(false); } + if (RefPtr mvm = + presShell->GetMobileViewportManager()) { + mvm->EnsureInitialViewportSet(); + } return nsRect(nsPoint(), presContext->GetVisibleArea().Size()); } diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index e7252c30f08a..db4ce4b1ce22 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -246,6 +246,7 @@ #include "mozilla/dom/WebIDLGlobalNameHash.h" #include "mozilla/dom/Worklet.h" #include "AccessCheck.h" +#include "MobileViewportManager.h" #ifdef HAVE_SIDEBAR # include "mozilla/dom/ExternalBinding.h" @@ -3549,7 +3550,7 @@ nsresult nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize) { NS_ENSURE_STATE(mDocShell); RefPtr presContext = mDocShell->GetPresContext(); - PresShell* presShell = mDocShell->GetPresShell(); + RefPtr presShell = mDocShell->GetPresShell(); if (!presContext || !presShell) { aSize = CSSIntSize(0, 0); @@ -3563,6 +3564,14 @@ nsresult nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize) { viewManager->FlushDelayedResize(false); } + // If this is called before the usual triggers for MVM to compute + // an initial viewport (load, DOMMetaAdded, first paint), compute + // one now. + if (RefPtr mvm = + presShell->GetMobileViewportManager()) { + mvm->EnsureInitialViewportSet(); + } + // FIXME: Bug 1598487 - Return the layout viewport instead of the ICB. nsSize viewportSize = presContext->GetVisibleArea().Size(); if (presContext->GetDynamicToolbarState() == DynamicToolbarState::Collapsed) { diff --git a/layout/base/MobileViewportManager.cpp b/layout/base/MobileViewportManager.cpp index 5463c92fce1c..73c80228abc5 100644 --- a/layout/base/MobileViewportManager.cpp +++ b/layout/base/MobileViewportManager.cpp @@ -183,6 +183,16 @@ MobileViewportManager::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } +void MobileViewportManager::EnsureInitialViewportSet() { + if (!mPainted) { + mIsFirstPaint = true; + // Do not set mPainted=true because we may not have a frame + // tree yet and we want to make sure SetInitialViewport() + // gets called once we have a frame tree. + RefreshViewportSize(false); + } +} + void MobileViewportManager::SetInitialViewport() { MVM_LOG("%p: setting initial viewport\n", this); mIsFirstPaint = true; diff --git a/layout/base/MobileViewportManager.h b/layout/base/MobileViewportManager.h index c580e701f407..d4c7649633f7 100644 --- a/layout/base/MobileViewportManager.h +++ b/layout/base/MobileViewportManager.h @@ -89,6 +89,17 @@ class MobileViewportManager final : public nsIDOMEventListener, * updated, and the visual viewport size needs to be updated. */ void ResolutionUpdated(mozilla::ResolutionChangeOrigin aOrigin); + /* Ensure that the initial viewport has been set based on the meta viewport + tag. There are two important differences between this and + SetInitialViewport(): + 1. This may be called before page load or before-first-paint, if + e.g. page content queries innerWidth early on. + 2. This has no effect if SetInitialViewport() has already been + called, and thus will not clobber a viewport that has + previously been set (and perhaps modified since then). + */ + void EnsureInitialViewportSet(); + /* Called to compute the initial viewport on page load or before-first-paint, * whichever happens first. Also called directly if we are created after the * presShell is initialized. */ diff --git a/testing/web-platform/meta/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js.ini b/testing/web-platform/meta/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js.ini deleted file mode 100644 index 8ece66ccf7a5..000000000000 --- a/testing/web-platform/meta/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js.ini +++ /dev/null @@ -1,9 +0,0 @@ -[noopener-noreferrer-sizing.window.html] - [window.open() with noreferrer should have equal viewport width and height] - expected: - if os == "android": FAIL - - [window.open() with noopener should have equal viewport width and height] - expected: - if os == "android": FAIL -