Bug 1423017 - Add a telemetry for out-of-reach overflowing on root. r=botond

MozReview-Commit-ID: 2CyZTVBFP59

--HG--
extra : rebase_source : 69792750af013f33ca9efd01c1d19013b0b26456
This commit is contained in:
Xidorn Quan 2018-06-01 15:35:32 +10:00
parent 8c597aa3d1
commit 51044f283f
4 changed files with 143 additions and 6 deletions

View File

@ -1497,6 +1497,7 @@ nsIDocument::nsIDocument()
mStackRefCnt(0), mStackRefCnt(0),
mUpdateNestLevel(0), mUpdateNestLevel(0),
mViewportType(Unknown), mViewportType(Unknown),
mViewportOverflowType(ViewportOverflowType::NoOverflow),
mSubDocuments(nullptr), mSubDocuments(nullptr),
mHeaderData(nullptr), mHeaderData(nullptr),
mFlashClassification(FlashClassification::Unclassified), mFlashClassification(FlashClassification::Unclassified),
@ -3690,6 +3691,7 @@ nsIDocument::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData)
aHeaderField == nsGkAtoms::viewport_width || aHeaderField == nsGkAtoms::viewport_width ||
aHeaderField == nsGkAtoms::viewport_user_scalable) { aHeaderField == nsGkAtoms::viewport_user_scalable) {
mViewportType = Unknown; mViewportType = Unknown;
mViewportOverflowType = ViewportOverflowType::NoOverflow;
} }
// Referrer policy spec says to ignore any empty referrer policies. // Referrer policy spec says to ignore any empty referrer policies.
@ -7237,6 +7239,7 @@ nsIDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode); mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
mViewportType = Specified; mViewportType = Specified;
mViewportOverflowType = ViewportOverflowType::NoOverflow;
MOZ_FALLTHROUGH; MOZ_FALLTHROUGH;
} }
case Specified: case Specified:
@ -7318,6 +7321,54 @@ nsIDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
} }
} }
void
nsIDocument::UpdateViewportOverflowType(nscoord aScrolledWidth,
nscoord aScrollportWidth)
{
#ifdef DEBUG
MOZ_ASSERT(mPresShell);
nsPresContext* pc = GetPresContext();
MOZ_ASSERT(pc->GetViewportScrollbarStylesOverride().mHorizontal ==
NS_STYLE_OVERFLOW_HIDDEN,
"Should only be called when viewport has overflow-x: hidden");
MOZ_ASSERT(aScrolledWidth > aScrollportWidth,
"Should only be called when viewport is overflowed");
MOZ_ASSERT(IsTopLevelContentDocument(),
"Should only be called for top-level content document");
#endif // DEBUG
if (!gfxPrefs::MetaViewportEnabled() ||
(GetWindow() && GetWindow()->IsDesktopModeViewport())) {
mViewportOverflowType = ViewportOverflowType::Desktop;
return;
}
static const LayoutDeviceToScreenScale
kBlinkDefaultMinScale = LayoutDeviceToScreenScale(0.25f);
LayoutDeviceToScreenScale minScale;
if (mViewportType == DisplayWidthHeight) {
minScale = kBlinkDefaultMinScale;
} else {
MOZ_ASSERT(mViewportType == Specified,
"Viewport information should have been initialized");
if (mScaleMinFloat == kViewportMinScale) {
minScale = kBlinkDefaultMinScale;
} else {
minScale = mScaleMinFloat;
}
}
// If the content has overflowed with minimum scale applied, don't
// change it, otherwise update the overflow type.
if (mViewportOverflowType != ViewportOverflowType::MinScaleSize) {
if (aScrolledWidth * minScale.scale < aScrollportWidth) {
mViewportOverflowType = ViewportOverflowType::ButNotMinScaleSize;
} else {
mViewportOverflowType = ViewportOverflowType::MinScaleSize;
}
}
}
EventListenerManager* EventListenerManager*
nsDocument::GetOrCreateListenerManager() nsDocument::GetOrCreateListenerManager()
{ {
@ -12132,6 +12183,23 @@ nsIDocument::ReportUseCounters(UseCounterReportKind aKind)
} }
} }
} }
if (IsTopLevelContentDocument() && !IsResourceDoc()) {
using mozilla::Telemetry::LABELS_HIDDEN_VIEWPORT_OVERFLOW_TYPE;
LABELS_HIDDEN_VIEWPORT_OVERFLOW_TYPE label;
switch (mViewportOverflowType) {
#define CASE_OVERFLOW_TYPE(t_) \
case ViewportOverflowType::t_: \
label = LABELS_HIDDEN_VIEWPORT_OVERFLOW_TYPE::t_; \
break;
CASE_OVERFLOW_TYPE(NoOverflow)
CASE_OVERFLOW_TYPE(Desktop)
CASE_OVERFLOW_TYPE(ButNotMinScaleSize)
CASE_OVERFLOW_TYPE(MinScaleSize)
#undef CASE_OVERFLOW_TYPE
}
Telemetry::AccumulateCategorical(label);
}
} }
void void

View File

@ -1199,6 +1199,17 @@ public:
*/ */
nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize); nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize);
/**
* It updates the viewport overflow type with the given two widths
* and the viewport setting of the document.
* This should only be called when there is out-of-reach overflow
* happens on the viewport, i.e. the viewport should be using
* `overflow: hidden`. And it should only be called on a top level
* content document.
*/
void UpdateViewportOverflowType(nscoord aScrolledWidth,
nscoord aScrollportWidth);
/** /**
* True iff this doc will ignore manual character encoding overrides. * True iff this doc will ignore manual character encoding overrides.
*/ */
@ -4271,7 +4282,7 @@ protected:
// Our update nesting level // Our update nesting level
uint32_t mUpdateNestLevel; uint32_t mUpdateNestLevel;
enum ViewportType { enum ViewportType : uint8_t {
DisplayWidthHeight, DisplayWidthHeight,
Specified, Specified,
Unknown Unknown
@ -4279,6 +4290,30 @@ protected:
ViewportType mViewportType; ViewportType mViewportType;
// Enum for how content in this document overflows viewport causing
// out-of-reach issue. Currently it only takes horizontal overflow
// into consideration. This enum and the corresponding field is only
// set and read on a top level content document.
enum class ViewportOverflowType : uint8_t {
// Viewport doesn't have out-of-reach overflow content, either
// because the content doesn't overflow, or the viewport doesn't
// have "overflow: hidden".
NoOverflow,
// All following items indicates that the content overflows the
// scroll port which causing out-of-reach content.
// Meta viewport is disabled or the document is in desktop mode.
Desktop,
// The content does not overflow the minimum-scale size. When there
// is no minimum scale specified, the default value used by Blink,
// 0.25, is used for this matter.
ButNotMinScaleSize,
// The content overflows the minimum-scale size.
MinScaleSize,
};
ViewportOverflowType mViewportOverflowType;
PLDHashTable* mSubDocuments; PLDHashTable* mSubDocuments;
nsDocHeaderData* mHeaderData; nsDocHeaderData* mHeaderData;

View File

@ -395,12 +395,12 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
std::max(0, compositionSize.height - hScrollbarDesiredHeight)); std::max(0, compositionSize.height - hScrollbarDesiredHeight));
} }
if (!aForce) { nsRect scrolledRect =
nsRect scrolledRect = mHelper.GetUnsnappedScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
mHelper.GetUnsnappedScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(), scrollPortSize);
scrollPortSize); nscoord oneDevPixel = aState->mBoxState.PresContext()->DevPixelsToAppUnits(1);
nscoord oneDevPixel = aState->mBoxState.PresContext()->DevPixelsToAppUnits(1);
if (!aForce) {
// If the style is HIDDEN then we already know that aAssumeHScroll is false // If the style is HIDDEN then we already know that aAssumeHScroll is false
if (aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { if (aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
bool wantHScrollbar = bool wantHScrollbar =
@ -426,6 +426,31 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
} }
} }
do {
if (!mHelper.mIsRoot) {
break;
}
// Check whether there is actually any overflow.
nscoord scrolledWidth = scrolledRect.width + oneDevPixel;
if (scrolledWidth <= scrollPortSize.width) {
break;
}
// Viewport scrollbar style is used below instead of aState->mStyles
// because the latter can be affected by various factors, while we
// only care about what the page itself specifies.
nsPresContext* pc = PresContext();
ScrollbarStyles styles = pc->GetViewportScrollbarStylesOverride();
if (styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
break;
}
// Only top level content document is considered.
nsIDocument* doc = pc->Document();
if (!doc->IsTopLevelContentDocument()) {
break;
}
doc->UpdateViewportOverflowType(scrolledWidth, scrollPortSize.width);
} while (false);
nscoord vScrollbarActualWidth = aState->mInsideBorderSize.width - scrollPortSize.width; nscoord vScrollbarActualWidth = aState->mInsideBorderSize.width - scrollPortSize.width;
aState->mShowHScrollbar = aAssumeHScroll; aState->mShowHScrollbar = aAssumeHScroll;

View File

@ -13804,5 +13804,14 @@
"high": 50, "high": 50,
"n_buckets": 20, "n_buckets": 20,
"description": "Total number of doc groups per tab group, including docgroups fully in bfcache. Collected at the point when the top level document of the tab group is unloaded." "description": "Total number of doc groups per tab group, including docgroups fully in bfcache. Collected at the point when the top level document of the tab group is unloaded."
},
"HIDDEN_VIEWPORT_OVERFLOW_TYPE": {
"record_in_processes": ["content"],
"alert_emails": ["xquan@mozilla.com", "botond@mozilla.com"],
"bug_numbers": [1423013, 1423017],
"expires_in_version": "65",
"kind": "categorical",
"labels": ["NoOverflow", "Desktop", "ButNotMinScaleSize", "MinScaleSize"],
"description": "How common are different types of out-of-reach viewport overflow?"
} }
} }