Bug 1366097 - Part 6. Restrict use of SVGImageContext in VectorImage::GetImageContainerAtSize to permitted URIs. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 17 Nov 2017 14:08:52 -0500
changeset 392505 e65c223336d99d8e7fae360b2fd3c1b10a91d531
parent 392504 54d6ad659f11103861cf2d53259d77764dfd675e
child 392506 71c36630c1416531830ae699dc766d118f83a4b5
push id32921
push usernerli@mozilla.com
push dateFri, 17 Nov 2017 22:02:18 +0000
treeherdermozilla-central@daa0dcd1616c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1366097
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1366097 - Part 6. Restrict use of SVGImageContext in VectorImage::GetImageContainerAtSize to permitted URIs. r=tnikkel
image/VectorImage.cpp
image/VectorImage.h
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -803,17 +803,18 @@ VectorImage::GetFrameInternal(const IntS
                               mSVGDocumentWrapper->GetCurrentTime(),
                               aFlags, 1.0);
 
   // DrawInternal may return a surface which is stored in the cache. It is
   // important to prefer this result over the snapshot because it may be a
   // different surface type (e.g. SourceSurfaceSharedData for WebRender). If
   // we did not put anything in the cache, we will need to fallback to the
   // snapshot surface.
-  RefPtr<SourceSurface> surface = DrawInternal(params, false);
+  bool contextPaint = aSVGContext && aSVGContext->GetContextPaint();
+  RefPtr<SourceSurface> surface = DrawInternal(params, contextPaint);
   if (!surface) {
     surface = dt->Snapshot();
   }
 
   return MakeTuple(DrawResult::SUCCESS, aSize, Move(surface));
 }
 
 //******************************************************************************
@@ -860,20 +861,71 @@ VectorImage::IsImageContainerAvailableAt
 
 //******************************************************************************
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 VectorImage::GetImageContainerAtSize(LayerManager* aManager,
                                      const IntSize& aSize,
                                      const Maybe<SVGImageContext>& aSVGContext,
                                      uint32_t aFlags)
 {
+  Maybe<SVGImageContext> newSVGContext;
+  MaybeRestrictSVGContext(newSVGContext, aSVGContext, aFlags);
+
   // Since we do not support high quality scaling with SVG, we mask it off so
   // that container requests with and without it map to the same container.
-  uint32_t flags = aFlags & ~FLAG_HIGH_QUALITY_SCALING;
-  return GetImageContainerImpl(aManager, aSize, aSVGContext, flags);
+  // Similarly the aspect ratio flag was already handled as part of the SVG
+  // context restriction above.
+  uint32_t flags = aFlags & ~(FLAG_HIGH_QUALITY_SCALING |
+                              FLAG_FORCE_PRESERVEASPECTRATIO_NONE);
+  return GetImageContainerImpl(aManager, aSize,
+                               newSVGContext ? newSVGContext : aSVGContext,
+                               flags);
+}
+
+bool
+VectorImage::MaybeRestrictSVGContext(Maybe<SVGImageContext>& aNewSVGContext,
+                                     const Maybe<SVGImageContext>& aSVGContext,
+                                     uint32_t aFlags)
+{
+  bool overridePAR = (aFlags & FLAG_FORCE_PRESERVEASPECTRATIO_NONE) && aSVGContext;
+
+  bool haveContextPaint = aSVGContext && aSVGContext->GetContextPaint();
+  bool blockContextPaint = false;
+  if (haveContextPaint) {
+    nsCOMPtr<nsIURI> imageURI = mURI->ToIURI();
+    blockContextPaint = !SVGContextPaint::IsAllowedForImageFromURI(imageURI);
+  }
+
+  if (overridePAR || blockContextPaint) {
+    // The key that we create for the image surface cache must match the way
+    // that the image will be painted, so we need to initialize a new matching
+    // SVGImageContext here in order to generate the correct key.
+
+    aNewSVGContext = aSVGContext; // copy
+
+    if (overridePAR) {
+      // The SVGImageContext must take account of the preserveAspectRatio
+      // overide:
+      MOZ_ASSERT(!aSVGContext->GetPreserveAspectRatio(),
+                 "FLAG_FORCE_PRESERVEASPECTRATIO_NONE is not expected if a "
+                 "preserveAspectRatio override is supplied");
+      Maybe<SVGPreserveAspectRatio> aspectRatio =
+        Some(SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE,
+                                    SVG_MEETORSLICE_UNKNOWN));
+      aNewSVGContext->SetPreserveAspectRatio(aspectRatio);
+    }
+
+    if (blockContextPaint) {
+      // The SVGImageContext must not include context paint if the image is
+      // not allowed to use it:
+      aNewSVGContext->ClearContextPaint();
+    }
+  }
+
+  return haveContextPaint && !blockContextPaint;
 }
 
 //******************************************************************************
 NS_IMETHODIMP_(DrawResult)
 VectorImage::Draw(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   uint32_t aWhichFrame,
@@ -902,54 +954,22 @@ VectorImage::Draw(gfxContext* aContext,
     SendOnUnlockedDraw(aFlags);
   }
 
   MOZ_ASSERT(!(aFlags & FLAG_FORCE_PRESERVEASPECTRATIO_NONE) ||
              (aSVGContext && aSVGContext->GetViewportSize()),
              "Viewport size is required when using "
              "FLAG_FORCE_PRESERVEASPECTRATIO_NONE");
 
-  bool overridePAR = (aFlags & FLAG_FORCE_PRESERVEASPECTRATIO_NONE) && aSVGContext;
-
-  bool haveContextPaint = aSVGContext && aSVGContext->GetContextPaint();
-  bool blockContextPaint = false;
-  if (haveContextPaint) {
-    nsCOMPtr<nsIURI> imageURI = mURI->ToIURI();
-    blockContextPaint = !SVGContextPaint::IsAllowedForImageFromURI(imageURI);
-  }
+  float animTime = (aWhichFrame == FRAME_FIRST)
+                     ? 0.0f : mSVGDocumentWrapper->GetCurrentTime();
 
   Maybe<SVGImageContext> newSVGContext;
-  if (overridePAR || blockContextPaint) {
-    // The key that we create for the image surface cache must match the way
-    // that the image will be painted, so we need to initialize a new matching
-    // SVGImageContext here in order to generate the correct key.
-
-    newSVGContext = aSVGContext; // copy
-
-    if (overridePAR) {
-      // The SVGImageContext must take account of the preserveAspectRatio
-      // overide:
-      MOZ_ASSERT(!aSVGContext->GetPreserveAspectRatio(),
-                 "FLAG_FORCE_PRESERVEASPECTRATIO_NONE is not expected if a "
-                 "preserveAspectRatio override is supplied");
-      Maybe<SVGPreserveAspectRatio> aspectRatio =
-        Some(SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE,
-                                    SVG_MEETORSLICE_UNKNOWN));
-      newSVGContext->SetPreserveAspectRatio(aspectRatio);
-    }
-
-    if (blockContextPaint) {
-      // The SVGImageContext must not include context paint if the image is
-      // not allowed to use it:
-      newSVGContext->ClearContextPaint();
-    }
-  }
-
-  float animTime = (aWhichFrame == FRAME_FIRST)
-                     ? 0.0f : mSVGDocumentWrapper->GetCurrentTime();
+  bool contextPaint =
+    MaybeRestrictSVGContext(newSVGContext, aSVGContext, aFlags);
 
   SVGDrawingParameters params(aContext, aSize, aRegion, aSamplingFilter,
                               newSVGContext ? newSVGContext : aSVGContext,
                               animTime, aFlags, aOpacity);
 
   // If we have an prerasterized version of this image that matches the
   // drawing parameters, use that.
   RefPtr<SourceSurface> sourceSurface =
@@ -963,18 +983,17 @@ VectorImage::Draw(gfxContext* aContext,
 
   // else, we need to paint the image:
 
   if (mIsDrawing) {
     NS_WARNING("Refusing to make re-entrant call to VectorImage::Draw");
     return DrawResult::TEMPORARY_ERROR;
   }
 
-  RefPtr<SourceSurface> surface =
-    DrawInternal(params, haveContextPaint && !blockContextPaint);
+  RefPtr<SourceSurface> surface = DrawInternal(params, contextPaint);
 
   // Image got put into a painted layer, it will not be shared with another
   // process.
   MarkSurfaceShared(surface);
   return DrawResult::SUCCESS;
 }
 
 already_AddRefed<SourceSurface>
--- a/image/VectorImage.h
+++ b/image/VectorImage.h
@@ -92,16 +92,20 @@ private:
                                 uint32_t aFlags) override;
 
   /// Attempt to find a matching cached surface in the SurfaceCache.
   already_AddRefed<SourceSurface>
     LookupCachedSurface(const IntSize& aSize,
                         const Maybe<SVGImageContext>& aSVGContext,
                         uint32_t aFlags);
 
+  bool MaybeRestrictSVGContext(Maybe<SVGImageContext>& aNewSVGContext,
+                               const Maybe<SVGImageContext>& aSVGContext,
+                               uint32_t aFlags);
+
   already_AddRefed<SourceSurface>
     DrawInternal(const SVGDrawingParameters& aParams, bool aContextPaint);
 
   already_AddRefed<SourceSurface>
     CreateSurfaceAndShow(const SVGDrawingParameters& aParams,
                          gfx::BackendType aBackend);
 
   void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);