Bug 1359762 - Only allow SVG images to use context paint if they're from chrome:// or resource://. r=dholbert
☠☠ backed out by 8d2edaa96316 ☠ ☠
authorJonathan Watt <jwatt@jwatt.org>
Thu, 13 Apr 2017 19:47:51 +0100
changeset 355738 de8bbf1eb20017db722ba77dbe3e187a4bbe359b
parent 355737 9542b21d8f462f31727c82bbeb214935085f763c
child 355739 561f117acfdb3c90d3c57315a1257771b2a352bd
push id41771
push userarchaeopteryx@coole-files.de
push dateSat, 29 Apr 2017 09:12:17 +0000
treeherderautoland@acca706f1eda [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1359762
milestone55.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 1359762 - Only allow SVG images to use context paint if they're from chrome:// or resource://. r=dholbert MozReview-Commit-ID: 5vaPp4Y8zMd
image/VectorImage.cpp
layout/svg/SVGContextPaint.cpp
layout/svg/SVGContextPaint.h
layout/svg/SVGImageContext.cpp
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -896,18 +896,21 @@ VectorImage::Draw(gfxContext* aContext,
   // Set the animation time:
   AutoSVGTimeSetRestore autoSVGTime(mSVGDocumentWrapper->GetRootSVGElem(),
                                     animTime);
 
   // Set context paint (if specified) on the document:
   Maybe<AutoSetRestoreSVGContextPaint> autoContextPaint;
   if (aSVGContext &&
       aSVGContext->GetContextPaint()) {
-    autoContextPaint.emplace(aSVGContext->GetContextPaint(),
-                             mSVGDocumentWrapper->GetDocument());
+    nsCOMPtr<nsIURI> uri = mURI->ToIURI();
+    if (SVGContextPaint::IsAllowedForImageFromURI(uri)) {
+      autoContextPaint.emplace(aSVGContext->GetContextPaint(),
+                               mSVGDocumentWrapper->GetDocument());
+    }
   }
 
   // We didn't get a hit in the surface cache, so we'll need to rerasterize.
   CreateSurfaceAndShow(params, aContext->GetDrawTarget()->GetBackendType());
   return DrawResult::SUCCESS;
 }
 
 already_AddRefed<gfxDrawable>
--- a/layout/svg/SVGContextPaint.cpp
+++ b/layout/svg/SVGContextPaint.cpp
@@ -2,26 +2,73 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SVGContextPaint.h"
 
 #include "gfxContext.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/Preferences.h"
 #include "nsIDocument.h"
 #include "nsSVGPaintServerFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGPaintServerFrame.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
 namespace mozilla {
 
+/* static */ bool
+SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
+{
+  static bool sEnabledForContent = false;
+  static bool sEnabledForContentCached = false;
+
+  if (!sEnabledForContentCached) {
+    Preferences::AddBoolVarCache(&sEnabledForContent,
+                                 "svg.context-properties.content.enabled", false);
+    sEnabledForContentCached = true;
+  }
+
+  if (sEnabledForContent) {
+    return true;
+  }
+
+  // Context paint is pref'ed off for Web content.  Ideally we'd have some
+  // easy means to determine whether the frame that has linked to the image
+  // is a frame for a content node that originated from Web content.
+  // Unfortunately different types of anonymous content, about: documents
+  // such as about:reader, etc. that are "our" code that we ship are
+  // sometimes hard to distinguish from real Web content.  As a result,
+  // instead of trying to figure out what content is "ours" we instead let
+  // any content provide image context paint, but only if the image is
+  // chrome:// or resource:// do we return true.  This should be sufficient
+  // to stop the image context paint feature being useful to (and therefore
+  // used by and relied upon by) Web content.  (We don't want Web content to
+  // use this feature because we're not sure that image context paint is a
+  // good mechanism for wider use, or suitable for specification.)
+  //
+  // One case where we may return false here and prevent image context paint
+  // being used by "our" content is in-tree WebExtensions.  These have scheme
+  // 'moz-extension://', but so do other developers' extensions, and we don't
+  // want extension developers coming to rely on image context paint either.
+  // We may be able to provide our in-tree extensions access to context paint
+  // once they are signed. For more information see:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1359762#c5
+  //
+  nsAutoCString scheme;
+  if (NS_SUCCEEDED(aURI->GetScheme(scheme)) &&
+      (scheme.EqualsLiteral("chrome") || scheme.EqualsLiteral("resource"))) {
+    return true;
+  }
+  return false;
+}
+
 /**
  * Stores in |aTargetPaint| information on how to reconstruct the current
  * fill or stroke pattern. Will also set the paint opacity to transparent if
  * the paint is set to "none".
  * @param aOuterContextPaint pattern information from the outer text context
  * @param aTargetPaint where to store the current pattern information
  * @param aFillOrStroke member pointer to the paint we are setting up
  * @param aProperty the frame property descriptor of the fill or stroke paint
--- a/layout/svg/SVGContextPaint.h
+++ b/layout/svg/SVGContextPaint.h
@@ -109,16 +109,22 @@ public:
 
   virtual uint32_t Hash() const {
     MOZ_ASSERT_UNREACHABLE("Only VectorImage needs to hash, and that should "
                            "only be operating on our SVGEmbeddingContextPaint "
                            "subclass");
     return 0;
   }
 
+  /**
+   * Returns true if image context paint is allowed to be used in an image that
+   * has the given URI, else returns false.
+   */
+  static bool IsAllowedForImageFromURI(nsIURI* aURI);
+
 private:
   // Member-vars are initialized in InitStrokeGeometry.
   FallibleTArray<gfxFloat> mDashes;
   MOZ_INIT_OUTSIDE_CTOR gfxFloat mDashOffset;
   MOZ_INIT_OUTSIDE_CTOR gfxFloat mStrokeWidth;
 };
 
 /**
--- a/layout/svg/SVGImageContext.cpp
+++ b/layout/svg/SVGImageContext.cpp
@@ -4,50 +4,35 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 // Main header first:
 #include "SVGImageContext.h"
 
 // Keep others in (case-insensitive) order:
 #include "gfxUtils.h"
-#include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
 #include "nsIFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleStruct.h"
 
 namespace mozilla {
 
 /* static */ void
 SVGImageContext::MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
                                         nsIFrame* aFromFrame,
                                         imgIContainer* aImgContainer)
 {
-  static bool sEnabledForContent = false;
-  static bool sEnabledForContentCached = false;
-
-  if (!sEnabledForContentCached) {
-    Preferences::AddBoolVarCache(&sEnabledForContent,
-                                 "svg.context-properties.content.enabled", false);
-    sEnabledForContentCached = true;
-  }
-
+  // This check is cheap, so we put it first:
   if (!aFromFrame->StyleSVG()->ExposesContextProperties()) {
     // Content must have '-moz-context-properties' set to the names of the
     // properties it wants to expose to images it links to.
     return;
   }
 
-  if (!sEnabledForContent &&
-      !nsContentUtils::IsChromeDoc(aFromFrame->PresContext()->Document())) {
-    // Context paint is pref'ed off for content and this is a content doc.
-    return;
-  }
-
   if (aImgContainer->GetType() != imgIContainer::TYPE_VECTOR) {
     // Avoid this overhead for raster images.
     return;
   }
 
   bool haveContextPaint = false;
 
   RefPtr<SVGEmbeddingContextPaint> contextPaint = new SVGEmbeddingContextPaint();