diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index e932022af1e..e25713060fd 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1570,6 +1570,13 @@ public: uint32_t aDisplayWidth, uint32_t aDisplayHeight); + /** + * Constrain the viewport calculations from the GetViewportInfo() function + * in order to always return sane minimum/maximum values. This modifies the + * ViewportInfo struct passed as an input parameter, in place. + */ + static void ConstrainViewportValues(ViewportInfo& aViewInfo); + /** * The device-pixel-to-CSS-px ratio used to adjust meta viewport values. */ diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index f716ce84c38..14a51d9df09 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -250,8 +250,8 @@ namespace { /** * Default values for the ViewportInfo structure. */ -static const float kViewportMinScale = 0.0; -static const float kViewportMaxScale = 10.0; +static const double kViewportMinScale = 0.0; +static const double kViewportMaxScale = 10.0; static const uint32_t kViewportMinWidth = 200; static const uint32_t kViewportMaxWidth = 10000; static const uint32_t kViewportMinHeight = 223; @@ -5101,6 +5101,29 @@ static void ProcessViewportToken(nsIDocument *aDocument, #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \ (c == '\t') || (c == '\n') || (c == '\r')) +/* static */ +void +nsContentUtils::ConstrainViewportValues(ViewportInfo& aViewInfo) +{ + aViewInfo.maxZoom = NS_MIN(aViewInfo.maxZoom, kViewportMaxScale); + aViewInfo.maxZoom = NS_MAX(aViewInfo.maxZoom, kViewportMinScale); + aViewInfo.minZoom = NS_MIN(aViewInfo.minZoom, kViewportMaxScale); + aViewInfo.minZoom = NS_MAX(aViewInfo.minZoom, kViewportMinScale); + + // Constrain the min/max zoom as specified at: + // dev.w3.org/csswg/css-device-adapt section 6.2 + aViewInfo.maxZoom = NS_MAX(aViewInfo.minZoom, aViewInfo.maxZoom); + + aViewInfo.defaultZoom = NS_MIN(aViewInfo.defaultZoom, aViewInfo.maxZoom); + aViewInfo.defaultZoom = NS_MAX(aViewInfo.defaultZoom, aViewInfo.minZoom); + + aViewInfo.width = NS_MIN(aViewInfo.width, kViewportMaxWidth); + aViewInfo.width = NS_MAX(aViewInfo.width, kViewportMinWidth); + + aViewInfo.height = NS_MIN(aViewInfo.height, kViewportMaxHeight); + aViewInfo.height = NS_MAX(aViewInfo.height, kViewportMinHeight); +} + /* static */ ViewportInfo nsContentUtils::GetViewportInfo(nsIDocument *aDocument, @@ -5111,6 +5134,10 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, ret.defaultZoom = 1.0; ret.autoSize = true; ret.allowZoom = true; + ret.width = aDisplayWidth; + ret.height = aDisplayHeight; + ret.minZoom = kViewportMinScale; + ret.maxZoom = kViewportMaxScale; nsAutoString viewport; aDocument->GetHeaderData(nsGkAtoms::viewport, viewport); @@ -5128,6 +5155,7 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, (docId.Find("Mobile") != -1) || (docId.Find("WML") != -1)) { + nsContentUtils::ConstrainViewportValues(ret); return ret; } } @@ -5136,6 +5164,7 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, nsAutoString handheldFriendly; aDocument->GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly); if (handheldFriendly.EqualsLiteral("true")) { + nsContentUtils::ConstrainViewportValues(ret); return ret; } } @@ -5150,9 +5179,6 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, scaleMinFloat = kViewportMinScale; } - scaleMinFloat = NS_MIN(scaleMinFloat, kViewportMaxScale); - scaleMinFloat = NS_MAX(scaleMinFloat, kViewportMinScale); - nsAutoString maxScaleStr; aDocument->GetHeaderData(nsGkAtoms::viewport_maximum_scale, maxScaleStr); @@ -5165,16 +5191,11 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, scaleMaxFloat = kViewportMaxScale; } - scaleMaxFloat = NS_MIN(scaleMaxFloat, kViewportMaxScale); - scaleMaxFloat = NS_MAX(scaleMaxFloat, kViewportMinScale); - nsAutoString scaleStr; aDocument->GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr); nsresult scaleErrorCode; float scaleFloat = scaleStr.ToFloat(&scaleErrorCode); - scaleFloat = NS_MIN(scaleFloat, scaleMaxFloat); - scaleFloat = NS_MAX(scaleFloat, scaleMinFloat); nsAutoString widthStr, heightStr; @@ -5235,18 +5256,12 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, } } - width = NS_MIN(width, kViewportMaxWidth); - width = NS_MAX(width, kViewportMinWidth); - // Also recalculate the default zoom, if it wasn't specified in the metadata, // and the width is specified. if (scaleStr.IsEmpty() && !widthStr.IsEmpty()) { scaleFloat = NS_MAX(scaleFloat, float(aDisplayWidth) / float(width)); } - height = NS_MIN(height, kViewportMaxHeight); - height = NS_MAX(height, kViewportMinHeight); - // We need to perform a conversion, but only if the initial or maximum // scale were set explicitly by the user. if (!scaleStr.IsEmpty() && NS_SUCCEEDED(scaleErrorCode)) { @@ -5274,6 +5289,8 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument, ret.minZoom = scaleMinFloat; ret.maxZoom = scaleMaxFloat; ret.autoSize = autoSize; + + nsContentUtils::ConstrainViewportValues(ret); return ret; } diff --git a/content/test/reftest/bug798068-ref.xhtml b/content/test/reftest/bug798068-ref.xhtml new file mode 100644 index 00000000000..2ddcd4a0218 --- /dev/null +++ b/content/test/reftest/bug798068-ref.xhtml @@ -0,0 +1,19 @@ + + + + + + + MinZoom:
+ MaxZoom: + + diff --git a/content/test/reftest/bug798068.xhtml b/content/test/reftest/bug798068.xhtml new file mode 100644 index 00000000000..6e2a6a35787 --- /dev/null +++ b/content/test/reftest/bug798068.xhtml @@ -0,0 +1,20 @@ + + + + + + + + MinZoom:
+ MaxZoom: + + diff --git a/content/test/reftest/reftest.list b/content/test/reftest/reftest.list index 206e8c876d6..1a299de9088 100644 --- a/content/test/reftest/reftest.list +++ b/content/test/reftest/reftest.list @@ -15,3 +15,4 @@ skip-if(xulFennec) include ../../canvas/test/reftest/reftest.list == bug592366-2.html bug592366-ref.html == bug592366-1.xhtml bug592366-ref.xhtml == bug592366-2.xhtml bug592366-ref.xhtml +== bug798068.xhtml bug798068-ref.xhtml