Bug 1359762 - Only allow SVG images to use context paint if they're from chrome:// or resource://. r=dholbert

MozReview-Commit-ID: 5vaPp4Y8zMd
This commit is contained in:
Jonathan Watt 2017-04-25 12:47:19 +01:00
Родитель 1385efd212
Коммит cfea97eb87
5 изменённых файлов: 90 добавлений и 27 удалений

Просмотреть файл

@ -812,18 +812,40 @@ VectorImage::Draw(gfxContext* aContext,
"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);
}
Maybe<SVGImageContext> newSVGContext;
if ((aFlags & FLAG_FORCE_PRESERVEASPECTRATIO_NONE) && aSVGContext) {
// Create an SVGImageContext with the appropriate 'preserveAspectRatio'
// value so that LookupCachedSurface() below uses the appropriate key:
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));
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
newSVGContext->SetPreserveAspectRatio(aspectRatio);
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)
@ -861,8 +883,7 @@ VectorImage::Draw(gfxContext* aContext,
// Set context paint (if specified) on the document:
Maybe<AutoSetRestoreSVGContextPaint> autoContextPaint;
if (aSVGContext &&
aSVGContext->GetContextPaint()) {
if (haveContextPaint && !blockContextPaint) {
autoContextPaint.emplace(aSVGContext->GetContextPaint(),
mSVGDocumentWrapper->GetDocument());
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "gfxContext.h"
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Preferences.h"
#include "nsIDocument.h"
#include "nsSVGPaintServerFrame.h"
#include "nsSVGEffects.h"
@ -17,6 +18,52 @@ 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

Просмотреть файл

@ -114,6 +114,12 @@ public:
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;

Просмотреть файл

@ -22,15 +22,6 @@ 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;
}
const nsStyleSVG* style = aFromFrame->StyleSVG();
if (!style->ExposesContextProperties()) {
@ -39,12 +30,6 @@ SVGImageContext::MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
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;

Просмотреть файл

@ -71,6 +71,10 @@ public:
return mContextPaint.get();
}
void ClearContextPaint() {
mContextPaint = nullptr;
}
bool operator==(const SVGImageContext& aOther) const {
bool contextPaintIsEqual =
// neither have context paint, or they have the same object: