Bug 1888242 - Simplify viewport handling in RDM. r=bradwerth,devtools-reviewers,ochameau

In particular:

 * Always handle meta viewport in RDM. This fixes bug 1625999 too by
   making touch simulation enabled and disabled consistent.

 * Restore the resolution to 1 when toggling RDM. This is just simpler,
   and we're not keeping around the visual viewport offsets anyways
   so...

 * Deal with the change more easily, at the same point we switch
   scrollbars etc.

Differential Revision: https://phabricator.services.mozilla.com/D206266
This commit is contained in:
Emilio Cobos Álvarez 2024-04-02 15:21:04 +00:00
parent bc4954f1d7
commit 8d73fd209e
12 changed files with 55 additions and 149 deletions

View file

@ -11,9 +11,6 @@ addRDMTask(TEST_URL, async function ({ ui, manager }) {
ok(ui, "An instance of the RDM should be attached to the tab."); ok(ui, "An instance of the RDM should be attached to the tab.");
await setViewportSizeAndAwaitReflow(ui, manager, 110, 500); await setViewportSizeAndAwaitReflow(ui, manager, 110, 500);
info("Checking initial width/height properties.");
await doInitialChecks(ui, 110);
info("Checking initial width/height with meta viewport on"); info("Checking initial width/height with meta viewport on");
await setTouchAndMetaViewportSupport(ui, true); await setTouchAndMetaViewportSupport(ui, true);
await doInitialChecks(ui, 980); await doInitialChecks(ui, 980);

View file

@ -6,18 +6,22 @@
// Check that when the viewport is resized, the computed-view refreshes. // Check that when the viewport is resized, the computed-view refreshes.
const TEST_URI = const TEST_URI =
"data:text/html;charset=utf-8,<html><style>" + "data:text/html;charset=utf-8," +
"div {" + `
" width: 500px;" + <meta name="viewport" content="width=device-width">
" height: 10px;" + <style>
" background: purple;" + div {
"} " + width: 500px;
"@media screen and (max-width: 200px) {" + height: 10px;
" div { " + background: purple;
" width: 100px;" + }
" }" + @media screen and (max-width: 200px) {
"};" + div {
"</style><div></div></html>"; width: 100px;
}
};
</style><div></div></html>
`;
addRDMTask(TEST_URI, async function ({ ui, manager }) { addRDMTask(TEST_URI, async function ({ ui, manager }) {
info("Open the responsive design mode and set its size to 500x500 to start"); info("Open the responsive design mode and set its size to 500x500 to start");

View file

@ -1,4 +1,5 @@
<html> <html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="doc_toolbox_rule_view.css"/> <link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="doc_toolbox_rule_view.css"/>
<div></div> <div></div>
</html> </html>

View file

@ -1338,10 +1338,6 @@ class WindowGlobalTargetActor extends BaseTargetActor {
if (typeof options.touchEventsOverride !== "undefined") { if (typeof options.touchEventsOverride !== "undefined") {
const enableTouchSimulator = options.touchEventsOverride === "enabled"; const enableTouchSimulator = options.touchEventsOverride === "enabled";
this.docShell.metaViewportOverride = enableTouchSimulator
? Ci.nsIDocShell.META_VIEWPORT_OVERRIDE_ENABLED
: Ci.nsIDocShell.META_VIEWPORT_OVERRIDE_NONE;
// We want to reload the document if it's an "existing" top level target on which // We want to reload the document if it's an "existing" top level target on which
// the touch simulator will be toggled and the user has turned the // the touch simulator will be toggled and the user has turned the
// "reload on touch simulation" setting on. // "reload on touch simulation" setting on.

View file

@ -333,7 +333,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAppType(nsIDocShell::APP_TYPE_UNKNOWN), mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
mLoadType(0), mLoadType(0),
mFailedLoadType(0), mFailedLoadType(0),
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
mChannelToDisconnectOnPageHide(0), mChannelToDisconnectOnPageHide(0),
mCreatingDocument(false), mCreatingDocument(false),
#ifdef DEBUG #ifdef DEBUG
@ -2377,37 +2376,6 @@ nsDocShell::ClearCachedUserAgent() {
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsDocShell::GetMetaViewportOverride(
MetaViewportOverride* aMetaViewportOverride) {
NS_ENSURE_ARG_POINTER(aMetaViewportOverride);
*aMetaViewportOverride = mMetaViewportOverride;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetMetaViewportOverride(
MetaViewportOverride aMetaViewportOverride) {
// We don't have a way to verify this coming from Javascript, so this check is
// still needed.
if (!(aMetaViewportOverride == META_VIEWPORT_OVERRIDE_NONE ||
aMetaViewportOverride == META_VIEWPORT_OVERRIDE_ENABLED ||
aMetaViewportOverride == META_VIEWPORT_OVERRIDE_DISABLED)) {
return NS_ERROR_INVALID_ARG;
}
mMetaViewportOverride = aMetaViewportOverride;
// Inform our presShell that it needs to re-check its need for a viewport
// override.
if (RefPtr<PresShell> presShell = GetPresShell()) {
presShell->MaybeRecreateMobileViewportManager(true);
}
return NS_OK;
}
/* virtual */ /* virtual */
int32_t nsDocShell::ItemType() { return mItemType; } int32_t nsDocShell::ItemType() { return mItemType; }
@ -2587,10 +2555,6 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
value = false; value = false;
} }
SetAllowDNSPrefetch(mAllowDNSPrefetch && value); SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
// We don't need to inherit metaViewportOverride, because the viewport
// is only relevant for the outermost nsDocShell, not for any iframes
// like this that might be embedded within it.
} }
nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent)); nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));

View file

@ -1267,10 +1267,6 @@ class nsDocShell final : public nsDocLoader,
uint32_t mLoadType; uint32_t mLoadType;
uint32_t mFailedLoadType; uint32_t mFailedLoadType;
// Whether or not handling of the <meta name="viewport"> tag is overridden.
// Possible values are defined as constants in nsIDocShell.idl.
MetaViewportOverride mMetaViewportOverride;
// See WindowGlobalParent::mSingleChannelId. // See WindowGlobalParent::mSingleChannelId.
mozilla::Maybe<uint64_t> mSingleChannelId; mozilla::Maybe<uint64_t> mSingleChannelId;
uint32_t mRequestForBlockingFromBFCacheCount = 0; uint32_t mRequestForBlockingFromBFCacheCount = 0;

View file

@ -646,31 +646,6 @@ interface nsIDocShell : nsIDocShellTreeItem
[noscript,nostdcall,notxpcom] nsCommandManager GetCommandManager(); [noscript,nostdcall,notxpcom] nsCommandManager GetCommandManager();
cenum MetaViewportOverride: 8 {
/**
* Override platform/pref default behaviour and force-disable support for
* <meta name="viewport">.
*/
META_VIEWPORT_OVERRIDE_DISABLED = 0,
/**
* Override platform/pref default behaviour and force-enable support for
* <meta name="viewport">.
*/
META_VIEWPORT_OVERRIDE_ENABLED = 1,
/**
* Don't override the platform/pref default behaviour for support for
* <meta name="viewport">.
*/
META_VIEWPORT_OVERRIDE_NONE = 2,
};
/**
* This allows chrome to override the default choice of whether the
* <meta name="viewport"> tag is respected in a specific docshell.
* Possible values are listed above.
*/
[infallible, setter_can_run_script] attribute nsIDocShell_MetaViewportOverride metaViewportOverride;
/** /**
* Attribute that determines whether tracking protection is enabled. * Attribute that determines whether tracking protection is enabled.
*/ */

View file

@ -1439,7 +1439,6 @@ Document::Document(const char* aContentType)
mThrowOnDynamicMarkupInsertionCounter(0), mThrowOnDynamicMarkupInsertionCounter(0),
mIgnoreOpensDuringUnloadCounter(0), mIgnoreOpensDuringUnloadCounter(0),
mSavedResolution(1.0f), mSavedResolution(1.0f),
mSavedResolutionBeforeMVM(1.0f),
mGeneration(0), mGeneration(0),
mCachedTabSizeGeneration(0), mCachedTabSizeGeneration(0),
mNextFormNumber(0), mNextFormNumber(0),

View file

@ -5313,9 +5313,6 @@ class Document : public nsINode,
// Pres shell resolution saved before entering fullscreen mode. // Pres shell resolution saved before entering fullscreen mode.
float mSavedResolution; float mSavedResolution;
// Pres shell resolution saved before creating a MobileViewportManager.
float mSavedResolutionBeforeMVM;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings; nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
bool mHasStoragePermission; bool mHasStoragePermission;
@ -5392,11 +5389,6 @@ class Document : public nsINode,
nsRefPtrHashtable<nsRefPtrHashKey<Element>, nsXULPrototypeElement> nsRefPtrHashtable<nsRefPtrHashKey<Element>, nsXULPrototypeElement>
mL10nProtoElements; mL10nProtoElements;
float GetSavedResolutionBeforeMVM() { return mSavedResolutionBeforeMVM; }
void SetSavedResolutionBeforeMVM(float aResolution) {
mSavedResolutionBeforeMVM = aResolution;
}
void LoadEventFired(); void LoadEventFired();
RadioGroupContainer& OwnedRadioGroupContainer(); RadioGroupContainer& OwnedRadioGroupContainer();

View file

@ -5657,7 +5657,7 @@ nsresult PresShell::SetResolutionAndScaleTo(float aResolution,
// GetResolution handles mResolution being nothing by returning 1 so this // GetResolution handles mResolution being nothing by returning 1 so this
// is checking that the resolution is actually changing. // is checking that the resolution is actually changing.
bool resolutionUpdated = (aResolution != GetResolution()); bool resolutionUpdated = aResolution != GetResolution();
mLastResolutionChangeOrigin = aOrigin; mLastResolutionChangeOrigin = aOrigin;
@ -11321,6 +11321,11 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
return; return;
} }
if (!mPresContext->IsRootContentDocumentCrossProcess()) {
MOZ_ASSERT(!mMobileViewportManager, "We never create MVMs for subframes");
return;
}
if (mMobileViewportManager) { if (mMobileViewportManager) {
// We have one, but we need to either destroy it completely to replace it // We have one, but we need to either destroy it completely to replace it
// with another one of the correct type. So either way, let's destroy the // with another one of the correct type. So either way, let's destroy the
@ -11330,16 +11335,6 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
mMVMContext = nullptr; mMVMContext = nullptr;
ResetVisualViewportSize(); ResetVisualViewportSize();
// After we clear out the MVM and the MVMContext, also reset the
// resolution to its pre-MVM value.
SetResolutionAndScaleTo(mDocument->GetSavedResolutionBeforeMVM(),
ResolutionChangeOrigin::MainThreadRestore);
if (aAfterInitialization) {
// Force a reflow to our correct view manager size.
ForceResizeReflowWithCurrentDimensions();
}
} }
if (mvmType) { if (mvmType) {
@ -11347,32 +11342,33 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
// have one. // have one.
MOZ_ASSERT(!mMobileViewportManager); MOZ_ASSERT(!mMobileViewportManager);
if (mPresContext->IsRootContentDocumentCrossProcess()) {
// Store the resolution so we can restore to this resolution when
// the MVM is destroyed.
mDocument->SetSavedResolutionBeforeMVM(mResolution.valueOr(1.0f));
mMVMContext = new GeckoMVMContext(mDocument, this); mMVMContext = new GeckoMVMContext(mDocument, this);
mMobileViewportManager = new MobileViewportManager(mMVMContext, *mvmType); mMobileViewportManager = new MobileViewportManager(mMVMContext, *mvmType);
if (MOZ_UNLIKELY( if (MOZ_UNLIKELY(
MOZ_LOG_TEST(MobileViewportManager::gLog, LogLevel::Debug))) { MOZ_LOG_TEST(MobileViewportManager::gLog, LogLevel::Debug))) {
nsIURI* uri = mDocument->GetDocumentURI(); nsIURI* uri = mDocument->GetDocumentURI();
MOZ_LOG(MobileViewportManager::gLog, LogLevel::Debug, MOZ_LOG(
("Created MVM %p (type %d) for URI %s", MobileViewportManager::gLog, LogLevel::Debug,
mMobileViewportManager.get(), (int)*mvmType, ("Created MVM %p (type %d) for URI %s", mMobileViewportManager.get(),
uri ? uri->GetSpecOrDefault().get() : "(null)")); (int)*mvmType, uri ? uri->GetSpecOrDefault().get() : "(null)"));
}
} }
if (aAfterInitialization) { if (aAfterInitialization) {
// Setting the initial viewport will trigger a reflow. // Setting the initial viewport will trigger a reflow.
if (mMobileViewportManager) {
mMobileViewportManager->SetInitialViewport(); mMobileViewportManager->SetInitialViewport();
} else {
// Force a reflow to our correct view manager size.
ForceResizeReflowWithCurrentDimensions();
} }
} // After we clear out the MVM and the MVMContext, also reset the
// resolution to 1.
SetResolutionAndScaleTo(1.0f, ResolutionChangeOrigin::MainThreadRestore);
} }
} }
bool PresShell::UsesMobileViewportSizing() const { bool PresShell::UsesMobileViewportSizing() const {
return mMobileViewportManager != nullptr && return mMobileViewportManager &&
nsLayoutUtils::ShouldHandleMetaViewport(mDocument); nsLayoutUtils::ShouldHandleMetaViewport(mDocument);
} }

View file

@ -714,12 +714,9 @@ bool nsLayoutUtils::AllowZoomingForDocument(
return false; return false;
} }
// True if we allow zooming for all documents on this platform, or if we are // True if we allow zooming for all documents on this platform, or if we are
// in RDM and handling meta viewports, which force zoom under some // in RDM.
// circumstances. BrowsingContext* bc = aDocument->GetBrowsingContext();
BrowsingContext* bc = aDocument ? aDocument->GetBrowsingContext() : nullptr; return StaticPrefs::apz_allow_zooming() || (bc && bc->InRDMPane());
return StaticPrefs::apz_allow_zooming() ||
(bc && bc->InRDMPane() &&
nsLayoutUtils::ShouldHandleMetaViewport(aDocument));
} }
static bool HasVisibleAnonymousContents(Document* aDoc) { static bool HasVisibleAnonymousContents(Document* aDoc) {
@ -9769,24 +9766,8 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
/* static */ /* static */
bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) { bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) {
auto metaViewportOverride = nsIDocShell::META_VIEWPORT_OVERRIDE_NONE; BrowsingContext* bc = aDocument->GetBrowsingContext();
if (aDocument) { return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane());
if (nsIDocShell* docShell = aDocument->GetDocShell()) {
metaViewportOverride = docShell->GetMetaViewportOverride();
}
}
switch (metaViewportOverride) {
case nsIDocShell::META_VIEWPORT_OVERRIDE_ENABLED:
return true;
case nsIDocShell::META_VIEWPORT_OVERRIDE_DISABLED:
return false;
default:
MOZ_ASSERT(metaViewportOverride ==
nsIDocShell::META_VIEWPORT_OVERRIDE_NONE);
// The META_VIEWPORT_OVERRIDE_NONE case means that there is no override
// and we rely solely on the StaticPrefs.
return StaticPrefs::dom_meta_viewport_enabled();
}
} }
/* static */ /* static */

View file

@ -1410,6 +1410,11 @@ void nsPresContext::SetInRDMPane(bool aInRDMPane) {
} }
mInRDMPane = aInRDMPane; mInRDMPane = aInRDMPane;
RecomputeTheme(); RecomputeTheme();
if (mPresShell) {
nsContentUtils::AddScriptRunner(NewRunnableMethod<bool>(
"PresShell::MaybeRecreateMobileViewportManager", mPresShell,
&PresShell::MaybeRecreateMobileViewportManager, true));
}
} }
float nsPresContext::GetDeviceFullZoom() { float nsPresContext::GetDeviceFullZoom() {