layout/svg/nsSVGFilterFrame.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 // Main header first:
     7 #include "nsSVGFilterFrame.h"
     9 // Keep others in (case-insensitive) order:
    10 #include "gfxUtils.h"
    11 #include "nsGkAtoms.h"
    12 #include "nsRenderingContext.h"
    13 #include "nsSVGEffects.h"
    14 #include "nsSVGElement.h"
    15 #include "mozilla/dom/SVGFilterElement.h"
    16 #include "nsSVGFilterInstance.h"
    17 #include "nsSVGFilterPaintCallback.h"
    18 #include "nsSVGIntegrationUtils.h"
    19 #include "nsSVGUtils.h"
    20 #include "nsContentUtils.h"
    22 using namespace mozilla::dom;
    24 nsIFrame*
    25 NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    26 {
    27   return new (aPresShell) nsSVGFilterFrame(aContext);
    28 }
    30 NS_IMPL_FRAMEARENA_HELPERS(nsSVGFilterFrame)
    32 class MOZ_STACK_CLASS nsSVGFilterFrame::AutoFilterReferencer
    33 {
    34 public:
    35   AutoFilterReferencer(nsSVGFilterFrame *aFrame MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    36     : mFrame(aFrame)
    37   {
    38     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    39     // Reference loops should normally be detected in advance and handled, so
    40     // we're not expecting to encounter them here
    41     NS_ABORT_IF_FALSE(!mFrame->mLoopFlag, "Undetected reference loop!");
    42     mFrame->mLoopFlag = true;
    43   }
    44   ~AutoFilterReferencer() {
    45     mFrame->mLoopFlag = false;
    46   }
    47 private:
    48   nsSVGFilterFrame *mFrame;
    49   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    50 };
    52 uint16_t
    53 nsSVGFilterFrame::GetEnumValue(uint32_t aIndex, nsIContent *aDefault)
    54 {
    55   nsSVGEnum& thisEnum =
    56     static_cast<SVGFilterElement *>(mContent)->mEnumAttributes[aIndex];
    58   if (thisEnum.IsExplicitlySet())
    59     return thisEnum.GetAnimValue();
    61   AutoFilterReferencer filterRef(this);
    63   nsSVGFilterFrame *next = GetReferencedFilterIfNotInUse();
    64   return next ? next->GetEnumValue(aIndex, aDefault) :
    65     static_cast<SVGFilterElement *>(aDefault)->
    66       mEnumAttributes[aIndex].GetAnimValue();
    67 }
    69 const nsSVGLength2 *
    70 nsSVGFilterFrame::GetLengthValue(uint32_t aIndex, nsIContent *aDefault)
    71 {
    72   const nsSVGLength2 *thisLength =
    73     &static_cast<SVGFilterElement *>(mContent)->mLengthAttributes[aIndex];
    75   if (thisLength->IsExplicitlySet())
    76     return thisLength;
    78   AutoFilterReferencer filterRef(this);
    80   nsSVGFilterFrame *next = GetReferencedFilterIfNotInUse();
    81   return next ? next->GetLengthValue(aIndex, aDefault) :
    82     &static_cast<SVGFilterElement *>(aDefault)->mLengthAttributes[aIndex];
    83 }
    85 const SVGFilterElement *
    86 nsSVGFilterFrame::GetFilterContent(nsIContent *aDefault)
    87 {
    88   for (nsIContent* child = mContent->GetFirstChild();
    89        child;
    90        child = child->GetNextSibling()) {
    91     nsRefPtr<nsSVGFE> primitive;
    92     CallQueryInterface(child, (nsSVGFE**)getter_AddRefs(primitive));
    93     if (primitive) {
    94       return static_cast<SVGFilterElement *>(mContent);
    95     }
    96   }
    98   AutoFilterReferencer filterRef(this);
   100   nsSVGFilterFrame *next = GetReferencedFilterIfNotInUse();
   101   return next ? next->GetFilterContent(aDefault) :
   102     static_cast<SVGFilterElement *>(aDefault);
   103 }
   105 nsSVGFilterFrame *
   106 nsSVGFilterFrame::GetReferencedFilter()
   107 {
   108   if (mNoHRefURI)
   109     return nullptr;
   111   nsSVGPaintingProperty *property = static_cast<nsSVGPaintingProperty*>
   112     (Properties().Get(nsSVGEffects::HrefProperty()));
   114   if (!property) {
   115     // Fetch our Filter element's xlink:href attribute
   116     SVGFilterElement *filter = static_cast<SVGFilterElement *>(mContent);
   117     nsAutoString href;
   118     filter->mStringAttributes[SVGFilterElement::HREF].GetAnimValue(href, filter);
   119     if (href.IsEmpty()) {
   120       mNoHRefURI = true;
   121       return nullptr; // no URL
   122     }
   124     // Convert href to an nsIURI
   125     nsCOMPtr<nsIURI> targetURI;
   126     nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
   127     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
   128                                               mContent->GetCurrentDoc(), base);
   130     property =
   131       nsSVGEffects::GetPaintingProperty(targetURI, this, nsSVGEffects::HrefProperty());
   132     if (!property)
   133       return nullptr;
   134   }
   136   nsIFrame *result = property->GetReferencedFrame();
   137   if (!result)
   138     return nullptr;
   140   nsIAtom* frameType = result->GetType();
   141   if (frameType != nsGkAtoms::svgFilterFrame)
   142     return nullptr;
   144   return static_cast<nsSVGFilterFrame*>(result);
   145 }
   147 nsSVGFilterFrame *
   148 nsSVGFilterFrame::GetReferencedFilterIfNotInUse()
   149 {
   150   nsSVGFilterFrame *referenced = GetReferencedFilter();
   151   if (!referenced)
   152     return nullptr;
   154   if (referenced->mLoopFlag) {
   155     // XXXjwatt: we should really send an error to the JavaScript Console here:
   156     NS_WARNING("Filter reference loop detected while inheriting attribute!");
   157     return nullptr;
   158   }
   160   return referenced;
   161 }
   163 nsresult
   164 nsSVGFilterFrame::AttributeChanged(int32_t  aNameSpaceID,
   165                                    nsIAtom* aAttribute,
   166                                    int32_t  aModType)
   167 {
   168   if (aNameSpaceID == kNameSpaceID_None &&
   169       (aAttribute == nsGkAtoms::x ||
   170        aAttribute == nsGkAtoms::y ||
   171        aAttribute == nsGkAtoms::width ||
   172        aAttribute == nsGkAtoms::height ||
   173        aAttribute == nsGkAtoms::filterUnits ||
   174        aAttribute == nsGkAtoms::primitiveUnits)) {
   175     nsSVGEffects::InvalidateDirectRenderingObservers(this);
   176   } else if (aNameSpaceID == kNameSpaceID_XLink &&
   177              aAttribute == nsGkAtoms::href) {
   178     // Blow away our reference, if any
   179     Properties().Delete(nsSVGEffects::HrefProperty());
   180     mNoHRefURI = false;
   181     // And update whoever references us
   182     nsSVGEffects::InvalidateDirectRenderingObservers(this);
   183   }
   184   return nsSVGFilterFrameBase::AttributeChanged(aNameSpaceID,
   185                                                 aAttribute, aModType);
   186 }
   188 #ifdef DEBUG
   189 void
   190 nsSVGFilterFrame::Init(nsIContent* aContent,
   191                        nsIFrame* aParent,
   192                        nsIFrame* aPrevInFlow)
   193 {
   194   NS_ASSERTION(aContent->IsSVG(nsGkAtoms::filter),
   195                "Content is not an SVG filter");
   197   nsSVGFilterFrameBase::Init(aContent, aParent, aPrevInFlow);
   198 }
   199 #endif /* DEBUG */
   201 nsIAtom *
   202 nsSVGFilterFrame::GetType() const
   203 {
   204   return nsGkAtoms::svgFilterFrame;
   205 }

mercurial