--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -82,315 +82,344 @@ const OperatingSystemVersionInfo osVersi
{ LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
{ LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
{ LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" }
};
#endif
// A helper for four features below
static nsSize
-GetSize(nsPresContext* aPresContext)
+GetSize(nsIDocument* aDocument)
+{
+ nsIPresShell* presShell = aDocument->GetShell();
+ if (!presShell) {
+ return { };
+ }
+
+ nsPresContext* pc = presShell->GetPresContext();
+ if (!pc) {
+ return { };
+ }
+
+ if (pc->IsRootPaginatedDocument()) {
+ // We want the page size, including unprintable areas and margins.
+ //
+ // FIXME(emilio, bug 1414600): Not quite!
+ return pc->GetPageSize();
+ }
+
+ return pc->GetVisibleArea().Size();
+}
+
+static void
+GetWidth(nsIDocument* aDocument, const nsMediaFeature*,
+ nsCSSValue& aResult)
+{
+ nsSize size = GetSize(aDocument);
+ aResult.SetFloatValue(CSSPixel::FromAppUnits(size.width), eCSSUnit_Pixel);
+}
+
+static void
+GetHeight(nsIDocument* aDocument, const nsMediaFeature*,
+ nsCSSValue& aResult)
{
+ nsSize size = GetSize(aDocument);
+ aResult.SetFloatValue(CSSPixel::FromAppUnits(size.height), eCSSUnit_Pixel);
+}
+
+static bool
+ShouldResistFingerprinting(nsIDocument* aDocument)
+{
+ return nsContentUtils::ShouldResistFingerprinting(aDocument->GetDocShell());
+}
+
+static bool
+IsDeviceSizePageSize(nsIDocument* aDocument)
+{
+ nsIDocShell* docShell = aDocument->GetDocShell();
+ if (!docShell) {
+ return false;
+ }
+ return docShell->GetDeviceSizeIsPageSize();
+}
+
+// A helper for three features below.
+static nsSize
+GetDeviceSize(nsIDocument* aDocument)
+{
+ if (ShouldResistFingerprinting(aDocument) || IsDeviceSizePageSize(aDocument)) {
+ return GetSize(aDocument);
+ }
+
+ nsIPresShell* presShell = aDocument->GetShell();
+ if (!presShell) {
+ return { };
+ }
+
+ nsPresContext* pc = presShell->GetPresContext();
+ if (!pc) {
+ return { };
+ }
+
+ if (pc->IsRootPaginatedDocument()) {
+ // We want the page size, including unprintable areas and margins.
+ // XXX The spec actually says we want the "page sheet size", but
+ // how is that different?
+ return pc->GetPageSize();
+ }
+
nsSize size;
- if (aPresContext->IsRootPaginatedDocument())
- // We want the page size, including unprintable areas and margins.
- size = aPresContext->GetPageSize();
- else
- size = aPresContext->GetVisibleArea().Size();
+ pc->DeviceContext()->GetDeviceSurfaceDimensions(size.width, size.height);
return size;
}
static void
-GetWidth(nsPresContext* aPresContext, const nsMediaFeature*,
- nsCSSValue& aResult)
+GetDeviceWidth(nsIDocument* aDocument, const nsMediaFeature*,
+ nsCSSValue& aResult)
{
- nsSize size = GetSize(aPresContext);
- float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
- aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
+ nsSize size = GetDeviceSize(aDocument);
+ aResult.SetFloatValue(CSSPixel::FromAppUnits(size.width), eCSSUnit_Pixel);
}
static void
-GetHeight(nsPresContext* aPresContext, const nsMediaFeature*,
- nsCSSValue& aResult)
-{
- nsSize size = GetSize(aPresContext);
- float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
- aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
-}
-
-inline static nsDeviceContext*
-GetDeviceContextFor(nsPresContext* aPresContext)
-{
- // It would be nice to call
- // nsLayoutUtils::GetDeviceContextForScreenInfo here, except for two
- // things: (1) it can flush, and flushing is bad here, and (2) it
- // doesn't really get us consistency in multi-monitor situations
- // *anyway*.
- return aPresContext->DeviceContext();
-}
-
-static bool
-ShouldResistFingerprinting(nsPresContext* aPresContext)
+GetDeviceHeight(nsIDocument* aDocument, const nsMediaFeature*,
+ nsCSSValue& aResult)
{
- return nsContentUtils::ShouldResistFingerprinting(aPresContext->GetDocShell());
-}
-
-// A helper for three features below.
-static nsSize
-GetDeviceSize(nsPresContext* aPresContext)
-{
- nsSize size;
-
- if (ShouldResistFingerprinting(aPresContext) || aPresContext->IsDeviceSizePageSize()) {
- size = GetSize(aPresContext);
- } else if (aPresContext->IsRootPaginatedDocument()) {
- // We want the page size, including unprintable areas and margins.
- // XXX The spec actually says we want the "page sheet size", but
- // how is that different?
- size = aPresContext->GetPageSize();
- } else {
- GetDeviceContextFor(aPresContext)->
- GetDeviceSurfaceDimensions(size.width, size.height);
- }
- return size;
+ nsSize size = GetDeviceSize(aDocument);
+ aResult.SetFloatValue(CSSPixel::FromAppUnits(size.height), eCSSUnit_Pixel);
}
static void
-GetDeviceWidth(nsPresContext* aPresContext, const nsMediaFeature*,
+GetOrientation(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- nsSize size = GetDeviceSize(aPresContext);
- float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
- aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
-}
-
-static void
-GetDeviceHeight(nsPresContext* aPresContext, const nsMediaFeature*,
- nsCSSValue& aResult)
-{
- nsSize size = GetDeviceSize(aPresContext);
- float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
- aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
-}
-
-static void
-GetOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
- nsCSSValue& aResult)
-{
- nsSize size = GetSize(aPresContext);
+ nsSize size = GetSize(aDocument);
int32_t orientation;
if (size.width > size.height) {
orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
} else {
// Per spec, square viewports should be 'portrait'
orientation = NS_STYLE_ORIENTATION_PORTRAIT;
}
aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
}
static void
-GetDeviceOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
+GetDeviceOrientation(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- nsSize size = GetDeviceSize(aPresContext);
- int32_t orientation;
- if (size.width > size.height) {
- orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
- } else {
- // Per spec, square viewports should be 'portrait'
- orientation = NS_STYLE_ORIENTATION_PORTRAIT;
- }
-
+ nsSize size = GetDeviceSize(aDocument);
+ // Per spec, square viewports should be 'portrait'
+ int32_t orientation = size.width > size.height
+ ? NS_STYLE_ORIENTATION_LANDSCAPE : NS_STYLE_ORIENTATION_PORTRAIT;
aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
}
static void
-GetIsResourceDocument(nsPresContext* aPresContext, const nsMediaFeature*,
+GetIsResourceDocument(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- nsIDocument* doc = aPresContext->Document();
- aResult.SetIntValue(doc && doc->IsResourceDoc() ? 1 : 0, eCSSUnit_Integer);
+ aResult.SetIntValue(aDocument->IsResourceDoc() ? 1 : 0, eCSSUnit_Integer);
}
// Helper for two features below
static void
MakeArray(const nsSize& aSize, nsCSSValue& aResult)
{
RefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
a->Item(0).SetIntValue(aSize.width, eCSSUnit_Integer);
a->Item(1).SetIntValue(aSize.height, eCSSUnit_Integer);
aResult.SetArrayValue(a, eCSSUnit_Array);
}
static void
-GetAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
+GetAspectRatio(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- MakeArray(GetSize(aPresContext), aResult);
+ MakeArray(GetSize(aDocument), aResult);
}
static void
-GetDeviceAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
+GetDeviceAspectRatio(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- MakeArray(GetDeviceSize(aPresContext), aResult);
+ MakeArray(GetDeviceSize(aDocument), aResult);
+}
+
+static nsDeviceContext*
+GetDeviceContextFor(nsIDocument* aDocument)
+{
+ nsIPresShell* shell = aDocument->GetShell();
+ if (!shell) {
+ return nullptr;
+ }
+
+ nsPresContext* pc = shell->GetPresContext();
+ if (!pc) {
+ return nullptr;
+ }
+
+ return pc->DeviceContext();
}
static void
-GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
+GetColor(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
uint32_t depth = 24; // Use depth of 24 when resisting fingerprinting.
- if (!ShouldResistFingerprinting(aPresContext)) {
- // FIXME: This implementation is bogus. nsDeviceContext
- // doesn't provide reliable information (should be fixed in bug
- // 424386).
- // FIXME: On a monochrome device, return 0!
- nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
- dx->GetDepth(depth);
+ if (!ShouldResistFingerprinting(aDocument)) {
+ if (nsDeviceContext* dx = GetDeviceContextFor(aDocument)) {
+ // FIXME: On a monochrome device, return 0!
+ dx->GetDepth(depth);
+ }
}
// The spec says to use bits *per color component*, so divide by 3,
// and round down, since the spec says to use the smallest when the
// color components differ.
depth /= 3;
aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer);
}
static void
-GetColorIndex(nsPresContext* aPresContext, const nsMediaFeature*,
+GetColorIndex(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// We should return zero if the device does not use a color lookup
// table. Stuart says that our handling of displays with 8-bit
// color is bad enough that we never change the lookup table to
// match what we're trying to display, so perhaps we should always
// return zero. Given that there isn't any better information
// exposed, we don't have much other choice.
aResult.SetIntValue(0, eCSSUnit_Integer);
}
static void
-GetMonochrome(nsPresContext* aPresContext, const nsMediaFeature*,
+GetMonochrome(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// For color devices we should return 0.
// FIXME: On a monochrome device, return the actual color depth, not
// 0!
aResult.SetIntValue(0, eCSSUnit_Integer);
}
static void
-GetResolution(nsPresContext* aPresContext, const nsMediaFeature*,
+GetResolution(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// We're returning resolution in terms of device pixels per css pixel, since
// that is the preferred unit for media queries of resolution. This avoids
// introducing precision error from conversion to and from less-used
// physical units like inches.
- float dppx;
+ float dppx = 1.;
- if (!ShouldResistFingerprinting(aPresContext)) {
- // Get the actual device pixel ratio, which also takes zoom into account.
- dppx = float(nsPresContext::AppUnitsPerCSSPixel()) /
- aPresContext->AppUnitsPerDevPixel();
- } else {
- // We are resisting fingerprinting, so pretend we have a device pixel ratio
- // of 1. In that case, we simply report the zoom level.
- dppx = aPresContext->GetDeviceFullZoom();
+ if (nsDeviceContext* dx = GetDeviceContextFor(aDocument)) {
+ if (ShouldResistFingerprinting(aDocument)) {
+ dppx = dx->GetFullZoom();
+ } else {
+ // Get the actual device pixel ratio, which also takes zoom into account.
+ dppx =
+ float(nsPresContext::AppUnitsPerCSSPixel()) / dx->AppUnitsPerDevPixel();
+ }
}
aResult.SetFloatValue(dppx, eCSSUnit_Pixel);
}
static void
-GetScan(nsPresContext* aPresContext, const nsMediaFeature*,
+GetScan(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// Since Gecko doesn't support the 'tv' media type, the 'scan'
// feature is never present.
aResult.Reset();
}
+static nsIDocument*
+TopDocument(nsIDocument* aDocument)
+{
+ nsIDocument* current = aDocument;
+ while (nsIDocument* parent = current->GetParentDocument()) {
+ current = parent;
+ }
+ return current;
+}
+
static void
-GetDisplayMode(nsPresContext* aPresContext, const nsMediaFeature*,
+GetDisplayMode(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- nsCOMPtr<nsISupports> container;
- RefPtr<nsIDocShell> docShell;
-
- if (!aPresContext) {
- aResult.SetIntValue(NS_STYLE_DISPLAY_MODE_BROWSER, eCSSUnit_Enumerated);
- return;
- }
+ nsIDocument* rootDocument = TopDocument(aDocument);
- if (aPresContext) {
- // Calling GetRootPresContext() can be slow, so make sure to call it
- // just once.
- nsRootPresContext* root = aPresContext->GetRootPresContext();
- if (root && root->Document()) {
- container = root->Document()->GetContainer();
- docShell = root->GetDocShell();
- }
- }
-
- nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
- if (baseWindow) {
+ nsCOMPtr<nsISupports> container = rootDocument->GetContainer();
+ if (nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container)) {
nsCOMPtr<nsIWidget> mainWidget;
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
- nsSizeMode mode = mainWidget ? mainWidget->SizeMode() : nsSizeMode_Normal;
-
- if (mode == nsSizeMode_Fullscreen) {
+ if (mainWidget && mainWidget->SizeMode() == nsSizeMode_Fullscreen) {
aResult.SetIntValue(NS_STYLE_DISPLAY_MODE_FULLSCREEN, eCSSUnit_Enumerated);
return;
}
}
static_assert(nsIDocShell::DISPLAY_MODE_BROWSER == NS_STYLE_DISPLAY_MODE_BROWSER &&
nsIDocShell::DISPLAY_MODE_MINIMAL_UI == NS_STYLE_DISPLAY_MODE_MINIMAL_UI &&
nsIDocShell::DISPLAY_MODE_STANDALONE == NS_STYLE_DISPLAY_MODE_STANDALONE &&
nsIDocShell::DISPLAY_MODE_FULLSCREEN == NS_STYLE_DISPLAY_MODE_FULLSCREEN,
"nsIDocShell display modes must mach nsStyleConsts.h");
uint32_t displayMode = NS_STYLE_DISPLAY_MODE_BROWSER;
- if (docShell) {
+ if (nsIDocShell* docShell = rootDocument->GetDocShell()) {
docShell->GetDisplayMode(&displayMode);
}
aResult.SetIntValue(displayMode, eCSSUnit_Enumerated);
}
static void
-GetGrid(nsPresContext* aPresContext, const nsMediaFeature*,
+GetGrid(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
// feature is always 0.
aResult.SetIntValue(0, eCSSUnit_Integer);
}
static void
-GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
+GetDevicePixelRatio(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
- if (!ShouldResistFingerprinting(aPresContext)) {
- float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
- aResult.SetFloatValue(ratio, eCSSUnit_Number);
- } else {
+ if (ShouldResistFingerprinting(aDocument)) {
+ aResult.SetFloatValue(1.0, eCSSUnit_Number);
+ return;
+ }
+
+ nsIPresShell* presShell = aDocument->GetShell();
+ if (!presShell) {
aResult.SetFloatValue(1.0, eCSSUnit_Number);
+ return;
}
+
+ nsPresContext* pc = presShell->GetPresContext();
+ if (!pc) {
+ aResult.SetFloatValue(1.0, eCSSUnit_Number);
+ return;
+ }
+
+ float ratio = pc->CSSPixelsToDevPixels(1.0f);
+ aResult.SetFloatValue(ratio, eCSSUnit_Number);
}
static void
-GetTransform3d(nsPresContext* aPresContext, const nsMediaFeature*,
+GetTransform3d(nsIDocument* aDocument, const nsMediaFeature*,
nsCSSValue& aResult)
{
// Gecko supports 3d transforms, so this feature is always 1.
aResult.SetIntValue(1, eCSSUnit_Integer);
}
static bool
HasSystemMetric(nsAtom* aMetric)
@@ -404,51 +433,50 @@ static uint8_t
GetWindowsThemeIdentifier()
{
nsMediaFeatures::InitSystemMetrics();
return sWinThemeId;
}
#endif
static void
-GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
+GetSystemMetric(nsIDocument* aDocument, const nsMediaFeature* aFeature,
nsCSSValue& aResult)
{
aResult.Reset();
const bool isAccessibleFromContentPages =
!(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly);
MOZ_ASSERT(!isAccessibleFromContentPages ||
*aFeature->mName == nsGkAtoms::_moz_touch_enabled);
- if (isAccessibleFromContentPages &&
- ShouldResistFingerprinting(aPresContext)) {
+ if (isAccessibleFromContentPages && ShouldResistFingerprinting(aDocument)) {
// If "privacy.resistFingerprinting" is enabled, then we simply don't
// return any system-backed media feature values. (No spoofed values
// returned.)
return;
}
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
"unexpected type");
nsAtom* metricAtom = *aFeature->mData.mMetric;
bool hasMetric = HasSystemMetric(metricAtom);
aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
}
static void
-GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
+GetWindowsTheme(nsIDocument* aDocument, const nsMediaFeature* aFeature,
nsCSSValue& aResult)
{
aResult.Reset();
MOZ_ASSERT(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly);
- if (ShouldResistFingerprinting(aPresContext)) {
+ if (ShouldResistFingerprinting(aDocument)) {
return;
}
#ifdef XP_WIN
uint8_t windowsThemeId = GetWindowsThemeIdentifier();
// Classic mode should fail to match.
if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)
@@ -461,23 +489,23 @@ GetWindowsTheme(nsPresContext* aPresCont
eCSSUnit_Ident);
break;
}
}
#endif
}
static void
-GetOperatingSystemVersion(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
+GetOperatingSystemVersion(nsIDocument* aDocument, const nsMediaFeature* aFeature,
nsCSSValue& aResult)
{
aResult.Reset();
MOZ_ASSERT(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly);
- if (ShouldResistFingerprinting(aPresContext)) {
+ if (ShouldResistFingerprinting(aDocument)) {
return;
}
#ifdef XP_WIN
int32_t metricResult;
if (NS_SUCCEEDED(
LookAndFeel::GetInt(LookAndFeel::eIntID_OperatingSystemVersionIdentifier,
&metricResult))) {
@@ -488,21 +516,21 @@ GetOperatingSystemVersion(nsPresContext*
break;
}
}
}
#endif
}
static void
-GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
- nsCSSValue& aResult)
+GetIsGlyph(nsIDocument* aDocument, const nsMediaFeature* aFeature,
+ nsCSSValue& aResult)
{
MOZ_ASSERT(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly);
- aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer);
+ aResult.SetIntValue(aDocument->IsSVGGlyphDocument() ? 1 : 0, eCSSUnit_Integer);
}
/* static */ void
nsMediaFeatures::InitSystemMetrics()
{
if (sSystemMetrics)
return;