Bug 1430608: Make nsMediaFeatures work with a document, not a pres context. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 15 Jan 2018 15:33:25 +0100
changeset 720640 d06fcfa8eb0f166e665c38ad24f74bdbbe11a93d
parent 720429 d3de2746024ab7baf325004318f098e519f525c0
child 720826 53d8ae1d1856592951529ec5578e19c016ccfd0f
push id95598
push userbmo:emilio@crisal.io
push dateMon, 15 Jan 2018 23:05:51 +0000
reviewersheycam
bugs1430608
milestone59.0a1
Bug 1430608: Make nsMediaFeatures work with a document, not a pres context. r?heycam Returning a zero-sized viewport in the case there's no shell / pres context. For now, no other change yet. After this we can start tweaking the ShadowRoot Stylist setup, and even try to return computed styles without a document \o/. MozReview-Commit-ID: 3cT2PKQISri
dom/base/nsIDocument.h
gfx/thebes/gfxSVGGlyphs.cpp
layout/base/nsPresContext.h
layout/style/nsMediaFeatures.cpp
layout/style/nsMediaFeatures.h
layout/style/nsMediaList.cpp
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGUtils.cpp
servo/components/style/gecko/media_queries.rs
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2210,16 +2210,24 @@ public:
   bool IsBeingUsedAsImage() const {
     return mIsBeingUsedAsImage;
   }
 
   void SetIsBeingUsedAsImage() {
     mIsBeingUsedAsImage = true;
   }
 
+  bool IsSVGGlyphDocument() const {
+    return mIsSVGGlyph;
+  }
+
+  void SetIsSVGGlyphDocument() {
+    mIsSVGGlyph = true;
+  }
+
   bool IsResourceDoc() const {
     return IsBeingUsedAsImage() || // Are we a helper-doc for an SVG image?
       mHasDisplayDocument;         // Are we an external resource doc?
   }
 
   /**
    * Get the document for which this document is an external resource.  This
    * will be null if this document is not an external resource.  Otherwise,
@@ -3531,16 +3539,19 @@ protected:
   bool mAllowPaymentRequest : 1;
 
   // True if the encoding menu should be disabled.
   bool mEncodingMenuDisabled : 1;
 
   // True if dom.webcomponents.enabled pref is set when document is created.
   bool mIsWebComponentsEnabled : 1;
 
+  // True if this document is for an SVG glyph.
+  bool mIsSVGGlyph : 1;
+
   // Whether <style scoped> support is enabled in this document.
   enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
   unsigned int mIsScopedStyleEnabled : 2;
 
   // Compatibility mode
   nsCompatibility mCompatMode;
 
   // Our readyState
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -152,21 +152,18 @@ gfxSVGGlyphsDocument::SetupPresentation(
     if (NS_SUCCEEDED(rv)) {
         rv = viewer->Open(nullptr, nullptr);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsCOMPtr<nsIPresShell> presShell;
     rv = viewer->GetPresShell(getter_AddRefs(presShell));
     NS_ENSURE_SUCCESS(rv, rv);
-    nsPresContext* presContext = presShell->GetPresContext();
-    presContext->SetIsGlyph(true);
-
     if (!presShell->DidInitialize()) {
-        nsRect rect = presContext->GetVisibleArea();
+        nsRect rect = presShell->GetPresContext()->GetVisibleArea();
         rv = presShell->Initialize(rect.Width(), rect.Height());
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     mDocument->FlushPendingNotifications(FlushType::Layout);
 
     if (mDocument->HasAnimationController()) {
       mDocument->GetAnimationController()
@@ -390,16 +387,17 @@ gfxSVGGlyphsDocument::ParseDocument(cons
                                   nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                                   nsIContentPolicy::TYPE_OTHER,
                                   SVG_CONTENT_TYPE,
                                   UTF8_CHARSET);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Set this early because various decisions during page-load depend on it.
     document->SetIsBeingUsedAsImage();
+    document->SetIsSVGGlyphDocument();
     document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
 
     nsCOMPtr<nsIStreamListener> listener;
     rv = document->StartDocumentLoad("external-resource", channel,
                                      nullptr,    // aLoadGroup
                                      nullptr,    // aContainer
                                      getter_AddRefs(listener),
                                      true /* aReset */);
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1119,24 +1119,16 @@ public:
   bool IsRootContentDocument() const;
 
   bool HadNonBlankPaint() const {
     return mHadNonBlankPaint;
   }
 
   void NotifyNonBlankPaint();
 
-  bool IsGlyph() const {
-    return mIsGlyph;
-  }
-
-  void SetIsGlyph(bool aValue) {
-    mIsGlyph = aValue;
-  }
-
   bool UsesRootEMUnits() const {
     return mUsesRootEMUnits;
   }
 
   void SetUsesRootEMUnits(bool aValue) {
     mUsesRootEMUnits = aValue;
   }
 
--- 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;
 
--- a/layout/style/nsMediaFeatures.h
+++ b/layout/style/nsMediaFeatures.h
@@ -7,21 +7,21 @@
 /* the features that media queries can test */
 
 #ifndef nsMediaFeatures_h_
 #define nsMediaFeatures_h_
 
 #include "nsCSSProps.h"
 
 class nsAtom;
-class nsPresContext;
+class nsIDocument;
 class nsCSSValue;
 
 struct nsMediaFeature;
-typedef void (*nsMediaFeatureValueGetter)(nsPresContext* aPresContext,
+typedef void (*nsMediaFeatureValueGetter)(nsIDocument* aDocument,
                                           const nsMediaFeature* aFeature,
                                           nsCSSValue& aResult);
 
 struct nsMediaFeature
 {
   nsStaticAtom** mName; // extra indirection to point to nsGkAtoms members
 
   enum RangeType { eMinMaxAllowed, eMinMaxNotAllowed };
--- a/layout/style/nsMediaList.cpp
+++ b/layout/style/nsMediaList.cpp
@@ -24,17 +24,17 @@ int32_t DoCompare(Numeric a, Numeric b)
   if (a == b)
     return 0;
   if (a < b)
     return -1;
   return 1;
 }
 
 bool
-nsMediaExpression::Matches(nsPresContext *aPresContext,
+nsMediaExpression::Matches(nsPresContext* aPresContext,
                            const nsCSSValue& aActualValue) const
 {
   const nsCSSValue& actual = aActualValue;
   const nsCSSValue& required = mValue;
 
   // If we don't have the feature, the match fails.
   if (actual.GetUnit() == eCSSUnit_Null) {
     return false;
@@ -216,17 +216,17 @@ nsMediaQueryResultCacheKey::Matches(nsPr
   if (aPresContext->Medium() != mMedium) {
     return false;
   }
 
   for (uint32_t i = 0; i < mFeatureCache.Length(); ++i) {
     const FeatureEntry *entry = &mFeatureCache[i];
     nsCSSValue actual;
 
-    entry->mFeature->mGetter(aPresContext, entry->mFeature, actual);
+    entry->mFeature->mGetter(aPresContext->Document(), entry->mFeature, actual);
 
     for (uint32_t j = 0; j < entry->mExpressions.Length(); ++j) {
       const ExpressionEntry &eentry = entry->mExpressions[j];
       if (eentry.mExpression.Matches(aPresContext, actual) !=
           eentry.mExpressionMatches) {
         return false;
       }
     }
@@ -471,17 +471,17 @@ nsMediaQuery::Matches(nsPresContext* aPr
   if (mHadUnknownExpression)
     return false;
 
   bool match =
     mMediaType == aPresContext->Medium() || mMediaType == nsGkAtoms::all;
   for (uint32_t i = 0, i_end = mExpressions.Length(); match && i < i_end; ++i) {
     const nsMediaExpression &expr = mExpressions[i];
     nsCSSValue actual;
-    expr.mFeature->mGetter(aPresContext, expr.mFeature, actual);
+    expr.mFeature->mGetter(aPresContext->Document(), expr.mFeature, actual);
 
     match = expr.Matches(aPresContext, actual);
     if (aKey) {
       aKey->AddExpression(&expr, match);
     }
   }
 
   return match == !mNegated;
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -255,17 +255,17 @@ nsSVGDisplayContainerFrame::IsSVGTransfo
 void
 nsSVGDisplayContainerFrame::PaintSVG(gfxContext& aContext,
                                      const gfxMatrix& aTransform,
                                      imgDrawingParams& aImgParams,
                                      const nsIntRect *aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY) ||
-               PresContext()->IsGlyph(),
+               PresContext()->Document()->IsSVGGlyphDocument(),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   if (StyleEffects()->mOpacity == 0.0) {
     return;
   }
 
   gfxMatrix matrix = aTransform;
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -652,17 +652,17 @@ void
 nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
                                   gfxContext& aContext,
                                   const gfxMatrix& aTransform,
                                   imgDrawingParams& aImgParams,
                                   const nsIntRect *aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
-               aFrame->PresContext()->IsGlyph(),
+               aFrame->PresContext()->Document()->IsSVGGlyphDocument(),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   nsSVGDisplayableFrame* svgFrame = do_QueryFrame(aFrame);
   if (!svgFrame)
     return;
 
   MaskUsage maskUsage;
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -679,19 +679,21 @@ impl Expression {
             Ok(Expression::new(feature, Some(value), range))
         })
     }
 
     /// Returns whether this media query evaluates to true for the given device.
     pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
         let mut css_value = nsCSSValue::null();
         unsafe {
-            (self.feature.mGetter.unwrap())(device.pres_context,
-                                            self.feature,
-                                            &mut css_value)
+            (self.feature.mGetter.unwrap())(
+                device.pres_context().mDocument.raw::<structs::nsIDocument>(),
+                self.feature,
+                &mut css_value,
+            )
         };
 
         let value = match MediaExpressionValue::from_css_value(self, &css_value) {
             Some(v) => v,
             None => return false,
         };
 
         self.evaluate_against(device, &value, quirks_mode)