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.");
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");
await setTouchAndMetaViewportSupport(ui, true);
await doInitialChecks(ui, 980);

View file

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

View file

@ -1,4 +1,5 @@
<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"/>
<div></div>
</html>

View file

@ -1338,10 +1338,6 @@ class WindowGlobalTargetActor extends BaseTargetActor {
if (typeof options.touchEventsOverride !== "undefined") {
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
// the touch simulator will be toggled and the user has turned the
// "reload on touch simulation" setting on.

View file

@ -333,7 +333,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
mLoadType(0),
mFailedLoadType(0),
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
mChannelToDisconnectOnPageHide(0),
mCreatingDocument(false),
#ifdef DEBUG
@ -2377,37 +2376,6 @@ nsDocShell::ClearCachedUserAgent() {
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 */
int32_t nsDocShell::ItemType() { return mItemType; }
@ -2587,10 +2555,6 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
value = false;
}
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));

View file

@ -1267,10 +1267,6 @@ class nsDocShell final : public nsDocLoader,
uint32_t mLoadType;
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.
mozilla::Maybe<uint64_t> mSingleChannelId;
uint32_t mRequestForBlockingFromBFCacheCount = 0;

View file

@ -646,31 +646,6 @@ interface nsIDocShell : nsIDocShellTreeItem
[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.
*/

View file

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

View file

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

View file

@ -5657,7 +5657,7 @@ nsresult PresShell::SetResolutionAndScaleTo(float aResolution,
// GetResolution handles mResolution being nothing by returning 1 so this
// is checking that the resolution is actually changing.
bool resolutionUpdated = (aResolution != GetResolution());
bool resolutionUpdated = aResolution != GetResolution();
mLastResolutionChangeOrigin = aOrigin;
@ -11321,6 +11321,11 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
return;
}
if (!mPresContext->IsRootContentDocumentCrossProcess()) {
MOZ_ASSERT(!mMobileViewportManager, "We never create MVMs for subframes");
return;
}
if (mMobileViewportManager) {
// 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
@ -11330,16 +11335,6 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
mMVMContext = nullptr;
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) {
@ -11347,32 +11342,33 @@ void PresShell::MaybeRecreateMobileViewportManager(bool aAfterInitialization) {
// have one.
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);
mMobileViewportManager = new MobileViewportManager(mMVMContext, *mvmType);
if (MOZ_UNLIKELY(
MOZ_LOG_TEST(MobileViewportManager::gLog, LogLevel::Debug))) {
nsIURI* uri = mDocument->GetDocumentURI();
MOZ_LOG(MobileViewportManager::gLog, LogLevel::Debug,
("Created MVM %p (type %d) for URI %s",
mMobileViewportManager.get(), (int)*mvmType,
uri ? uri->GetSpecOrDefault().get() : "(null)"));
}
if (aAfterInitialization) {
// Setting the initial viewport will trigger a reflow.
mMobileViewportManager->SetInitialViewport();
}
mMVMContext = new GeckoMVMContext(mDocument, this);
mMobileViewportManager = new MobileViewportManager(mMVMContext, *mvmType);
if (MOZ_UNLIKELY(
MOZ_LOG_TEST(MobileViewportManager::gLog, LogLevel::Debug))) {
nsIURI* uri = mDocument->GetDocumentURI();
MOZ_LOG(
MobileViewportManager::gLog, LogLevel::Debug,
("Created MVM %p (type %d) for URI %s", mMobileViewportManager.get(),
(int)*mvmType, uri ? uri->GetSpecOrDefault().get() : "(null)"));
}
}
if (aAfterInitialization) {
// Setting the initial viewport will trigger a reflow.
if (mMobileViewportManager) {
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 {
return mMobileViewportManager != nullptr &&
return mMobileViewportManager &&
nsLayoutUtils::ShouldHandleMetaViewport(mDocument);
}

View file

@ -714,12 +714,9 @@ bool nsLayoutUtils::AllowZoomingForDocument(
return false;
}
// 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
// circumstances.
BrowsingContext* bc = aDocument ? aDocument->GetBrowsingContext() : nullptr;
return StaticPrefs::apz_allow_zooming() ||
(bc && bc->InRDMPane() &&
nsLayoutUtils::ShouldHandleMetaViewport(aDocument));
// in RDM.
BrowsingContext* bc = aDocument->GetBrowsingContext();
return StaticPrefs::apz_allow_zooming() || (bc && bc->InRDMPane());
}
static bool HasVisibleAnonymousContents(Document* aDoc) {
@ -9769,24 +9766,8 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
/* static */
bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) {
auto metaViewportOverride = nsIDocShell::META_VIEWPORT_OVERRIDE_NONE;
if (aDocument) {
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();
}
BrowsingContext* bc = aDocument->GetBrowsingContext();
return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane());
}
/* static */

View file

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