bug 793755 - Talos Regressions Trobopan, Tdhtml, tp4m_nochrome on Sept 22, cache information about the viewport r=jwir3

This commit is contained in:
Brad Lassey 2013-01-03 22:27:06 -05:00
parent 613983a388
commit 6cb0d7645f
4 changed files with 217 additions and 158 deletions

View File

@ -75,6 +75,7 @@ class nsTextNode;
class nsWindowSizes;
class nsSmallVoidArray;
class nsDOMCaretPosition;
class nsViewportInfo;
namespace mozilla {
class ErrorResult;
@ -562,6 +563,10 @@ public:
*/
Element* GetRootElement() const;
virtual nsViewportInfo GetViewportInfo(uint32_t aDisplayWidth,
uint32_t aDisplayHeight) = 0;
protected:
virtual Element *GetRootElementInternal() const = 0;

View File

@ -5053,164 +5053,7 @@ nsContentUtils::GetViewportInfo(nsIDocument *aDocument,
uint32_t aDisplayWidth,
uint32_t aDisplayHeight)
{
nsAutoString viewport;
aDocument->GetHeaderData(nsGkAtoms::viewport, viewport);
if (viewport.IsEmpty()) {
// If the docType specifies that we are on a site optimized for mobile,
// then we want to return specially crafted defaults for the viewport info.
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(aDocument));
nsCOMPtr<nsIDOMDocumentType> docType;
nsresult rv = domDoc->GetDoctype(getter_AddRefs(docType));
if (NS_SUCCEEDED(rv) && docType) {
nsAutoString docId;
rv = docType->GetPublicId(docId);
if (NS_SUCCEEDED(rv)) {
if ((docId.Find("WAP") != -1) ||
(docId.Find("Mobile") != -1) ||
(docId.Find("WML") != -1))
{
nsViewportInfo ret(aDisplayWidth, aDisplayHeight);
return ret;
}
}
}
nsAutoString handheldFriendly;
aDocument->GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly);
if (handheldFriendly.EqualsLiteral("true")) {
nsViewportInfo ret(aDisplayWidth, aDisplayHeight);
return ret;
}
}
nsAutoString minScaleStr;
aDocument->GetHeaderData(nsGkAtoms::viewport_minimum_scale, minScaleStr);
nsresult errorCode;
float scaleMinFloat = minScaleStr.ToFloat(&errorCode);
if (NS_FAILED(errorCode)) {
scaleMinFloat = kViewportMinScale;
}
scaleMinFloat = NS_MIN((double)scaleMinFloat, kViewportMaxScale);
scaleMinFloat = NS_MAX((double)scaleMinFloat, kViewportMinScale);
nsAutoString maxScaleStr;
aDocument->GetHeaderData(nsGkAtoms::viewport_maximum_scale, maxScaleStr);
// We define a special error code variable for the scale and max scale,
// because they are used later (see the width calculations).
nsresult scaleMaxErrorCode;
float scaleMaxFloat = maxScaleStr.ToFloat(&scaleMaxErrorCode);
if (NS_FAILED(scaleMaxErrorCode)) {
scaleMaxFloat = kViewportMaxScale;
}
scaleMaxFloat = NS_MIN((double)scaleMaxFloat, kViewportMaxScale);
scaleMaxFloat = NS_MAX((double)scaleMaxFloat, kViewportMinScale);
nsAutoString scaleStr;
aDocument->GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr);
nsresult scaleErrorCode;
float scaleFloat = scaleStr.ToFloat(&scaleErrorCode);
nsAutoString widthStr, heightStr;
aDocument->GetHeaderData(nsGkAtoms::viewport_height, heightStr);
aDocument->GetHeaderData(nsGkAtoms::viewport_width, widthStr);
bool autoSize = false;
if (widthStr.EqualsLiteral("device-width")) {
autoSize = true;
}
if (widthStr.IsEmpty() &&
(heightStr.EqualsLiteral("device-height") ||
scaleFloat == 1.0))
{
autoSize = true;
}
// Now convert the scale into device pixels per CSS pixel.
nsIWidget *widget = WidgetForDocument(aDocument);
double pixelRatio = widget ? GetDevicePixelsPerMetaViewportPixel(widget) : 1.0;
scaleFloat *= pixelRatio;
scaleMinFloat *= pixelRatio;
scaleMaxFloat *= pixelRatio;
uint32_t width, height;
if (autoSize) {
// aDisplayWidth and aDisplayHeight are in device pixels; convert them to
// CSS pixels for the viewport size.
width = aDisplayWidth / pixelRatio;
height = aDisplayHeight / pixelRatio;
} else {
nsresult widthErrorCode, heightErrorCode;
width = widthStr.ToInteger(&widthErrorCode);
height = heightStr.ToInteger(&heightErrorCode);
// If width or height has not been set to a valid number by this point,
// fall back to a default value.
bool validWidth = (!widthStr.IsEmpty() && NS_SUCCEEDED(widthErrorCode) && width > 0);
bool validHeight = (!heightStr.IsEmpty() && NS_SUCCEEDED(heightErrorCode) && height > 0);
if (!validWidth) {
if (validHeight && aDisplayWidth > 0 && aDisplayHeight > 0) {
width = uint32_t((height * aDisplayWidth) / aDisplayHeight);
} else {
width = Preferences::GetInt("browser.viewport.desktopWidth",
kViewportDefaultScreenWidth);
}
}
if (!validHeight) {
if (aDisplayWidth > 0 && aDisplayHeight > 0) {
height = uint32_t((width * aDisplayHeight) / aDisplayWidth);
} else {
height = width;
}
}
}
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)) {
width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleFloat));
height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleFloat));
} else if (!maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode)) {
width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleMaxFloat));
height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleMaxFloat));
}
bool allowZoom = true;
nsAutoString userScalable;
aDocument->GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
if ((userScalable.EqualsLiteral("0")) ||
(userScalable.EqualsLiteral("no")) ||
(userScalable.EqualsLiteral("false"))) {
allowZoom = false;
}
nsViewportInfo ret(scaleFloat, scaleMinFloat, scaleMaxFloat, width, height,
autoSize, allowZoom);
return ret;
return aDocument->GetViewportInfo(aDisplayWidth, aDisplayHeight);
}
/* static */

View File

@ -188,6 +188,7 @@
#include "nsFrame.h"
#include "nsDOMCaretPosition.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsViewportInfo.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1326,6 +1327,7 @@ nsIDocument::nsIDocument()
nsDocument::nsDocument(const char* aContentType)
: nsIDocument()
, mAnimatingImages(true)
, mViewportType(Unknown)
{
SetContentTypeInternal(nsDependentCString(aContentType));
@ -3089,6 +3091,17 @@ nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData)
// Chromium treats any value other than 'on' (case insensitive) as 'off'.
mAllowDNSPrefetch = aData.IsEmpty() || aData.LowerCaseEqualsLiteral("on");
}
if (aHeaderField == nsGkAtoms::viewport ||
aHeaderField == nsGkAtoms::handheldFriendly ||
aHeaderField == nsGkAtoms::viewport_minimum_scale ||
aHeaderField == nsGkAtoms::viewport_maximum_scale ||
aHeaderField == nsGkAtoms::viewport_initial_scale ||
aHeaderField == nsGkAtoms::viewport_height ||
aHeaderField == nsGkAtoms::viewport_width ||
aHeaderField == nsGkAtoms::viewport_user_scalable) {
mViewportType = Unknown;
}
}
bool
@ -6376,6 +6389,186 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
return adoptedNode;
}
nsViewportInfo
nsDocument::GetViewportInfo(uint32_t aDisplayWidth,
uint32_t aDisplayHeight)
{
switch (mViewportType) {
case DisplayWidthHeight:
return nsViewportInfo(aDisplayWidth, aDisplayHeight);
case Unknown:
{
nsAutoString viewport;
GetHeaderData(nsGkAtoms::viewport, viewport);
if (viewport.IsEmpty()) {
// If the docType specifies that we are on a site optimized for mobile,
// then we want to return specially crafted defaults for the viewport info.
nsCOMPtr<nsIDOMDocumentType> docType;
nsresult rv = GetDoctype(getter_AddRefs(docType));
if (NS_SUCCEEDED(rv) && docType) {
nsAutoString docId;
rv = docType->GetPublicId(docId);
if (NS_SUCCEEDED(rv)) {
if ((docId.Find("WAP") != -1) ||
(docId.Find("Mobile") != -1) ||
(docId.Find("WML") != -1))
{
mViewportType = DisplayWidthHeight;
nsViewportInfo ret(aDisplayWidth, aDisplayHeight);
return ret;
}
}
}
nsAutoString handheldFriendly;
GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly);
if (handheldFriendly.EqualsLiteral("true")) {
mViewportType = DisplayWidthHeight;
nsViewportInfo ret(aDisplayWidth, aDisplayHeight);
return ret;
}
}
nsAutoString minScaleStr;
GetHeaderData(nsGkAtoms::viewport_minimum_scale, minScaleStr);
nsresult errorCode;
mScaleMinFloat = minScaleStr.ToFloat(&errorCode);
if (NS_FAILED(errorCode)) {
mScaleMinFloat = kViewportMinScale;
}
mScaleMinFloat = NS_MIN((double)mScaleMinFloat, kViewportMaxScale);
mScaleMinFloat = NS_MAX((double)mScaleMinFloat, kViewportMinScale);
nsAutoString maxScaleStr;
GetHeaderData(nsGkAtoms::viewport_maximum_scale, maxScaleStr);
// We define a special error code variable for the scale and max scale,
// because they are used later (see the width calculations).
nsresult scaleMaxErrorCode;
mScaleMaxFloat = maxScaleStr.ToFloat(&scaleMaxErrorCode);
if (NS_FAILED(scaleMaxErrorCode)) {
mScaleMaxFloat = kViewportMaxScale;
}
mScaleMaxFloat = NS_MIN((double)mScaleMaxFloat, kViewportMaxScale);
mScaleMaxFloat = NS_MAX((double)mScaleMaxFloat, kViewportMinScale);
nsAutoString scaleStr;
GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr);
nsresult scaleErrorCode;
mScaleFloat = scaleStr.ToFloat(&scaleErrorCode);
nsAutoString widthStr, heightStr;
GetHeaderData(nsGkAtoms::viewport_height, heightStr);
GetHeaderData(nsGkAtoms::viewport_width, widthStr);
mAutoSize = false;
if (widthStr.EqualsLiteral("device-width")) {
mAutoSize = true;
}
if (widthStr.IsEmpty() && heightStr.EqualsLiteral("device-height")) {
mAutoSize = true;
}
nsresult widthErrorCode, heightErrorCode;
mViewportWidth = widthStr.ToInteger(&widthErrorCode);
mViewportHeight = heightStr.ToInteger(&heightErrorCode);
// If width or height has not been set to a valid number by this point,
// fall back to a default value.
bool validWidth = (!widthStr.IsEmpty() && NS_SUCCEEDED(widthErrorCode) && mViewportWidth > 0);
bool validHeight = (!heightStr.IsEmpty() && NS_SUCCEEDED(heightErrorCode) && mViewportHeight > 0);
if (!validWidth) {
if (validHeight && aDisplayWidth > 0 && aDisplayHeight > 0) {
mViewportWidth = uint32_t((mViewportHeight * aDisplayWidth) / aDisplayHeight);
} else {
mViewportWidth = Preferences::GetInt("browser.viewport.desktopWidth",
kViewportDefaultScreenWidth);
}
}
if (!validHeight) {
if (aDisplayWidth > 0 && aDisplayHeight > 0) {
mViewportHeight = uint32_t((mViewportWidth * aDisplayHeight) / aDisplayWidth);
} else {
mViewportHeight = mViewportWidth;
}
}
mAllowZoom = true;
nsAutoString userScalable;
GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
if ((userScalable.EqualsLiteral("0")) ||
(userScalable.EqualsLiteral("no")) ||
(userScalable.EqualsLiteral("false"))) {
mAllowZoom = false;
}
mScaleStrEmpty = scaleStr.IsEmpty();
mWidthStrEmpty = widthStr.IsEmpty();
mValidScaleFloat = !scaleStr.IsEmpty() && NS_SUCCEEDED(scaleErrorCode);
mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
mViewportType = Specified;
}
case Specified:
default:
// Now convert the scale into device pixels per CSS pixel.
nsIWidget *widget = nsContentUtils::WidgetForDocument(this);
double pixelRatio = widget ? nsContentUtils::GetDevicePixelsPerMetaViewportPixel(widget) : 1.0;
float scaleFloat = mScaleFloat * pixelRatio;
float scaleMinFloat= mScaleMinFloat * pixelRatio;
float scaleMaxFloat = mScaleMaxFloat * pixelRatio;
uint32_t width, height;
if (mAutoSize) {
// aDisplayWidth and aDisplayHeight are in device pixels; convert them to
// CSS pixels for the viewport size.
width = aDisplayWidth / pixelRatio;
height = aDisplayHeight / pixelRatio;
} else {
width = mViewportWidth;
height = mViewportHeight;
}
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 (mScaleStrEmpty && !mWidthStrEmpty) {
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 (mValidScaleFloat) {
width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleFloat));
height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleFloat));
} else if (mValidMaxScale) {
width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleMaxFloat));
height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleMaxFloat));
}
nsViewportInfo ret(scaleFloat, scaleMinFloat, scaleMaxFloat, width, height,
mAutoSize || (mWidthStrEmpty && scaleFloat == 1.0), mAllowZoom);
return ret;
}
}
nsEventListenerManager*
nsDocument::GetListenerManager(bool aCreateIfNotFound)
{

View File

@ -738,6 +738,10 @@ public:
nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const;
nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
virtual nsViewportInfo GetViewportInfo(uint32_t aDisplayWidth,
uint32_t aDisplayHeight);
private:
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
@ -1359,6 +1363,20 @@ private:
nsRefPtr<mozilla::dom::UndoManager> mUndoManager;
enum ViewportType {
DisplayWidthHeight,
Specified,
Unknown
};
ViewportType mViewportType;
// These member variables cache information about the viewport so we don't have to
// recalculate it each time.
float mScaleMinFloat, mScaleMaxFloat, mScaleFloat, mPixelRatio;
bool mAutoSize, mAllowZoom, mValidScaleFloat, mValidMaxScale, mScaleStrEmpty, mWidthStrEmpty;
uint32_t mViewportWidth, mViewportHeight;
#ifdef DEBUG
protected:
bool mWillReparent;