tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGAElement.cpp (9177B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/SVGAElement.h"
      8 
      9 #include "mozilla/EventDispatcher.h"
     10 #include "mozilla/FocusModel.h"
     11 #include "mozilla/dom/DocumentInlines.h"
     12 #include "mozilla/dom/SVGAElementBinding.h"
     13 #include "nsCOMPtr.h"
     14 #include "nsContentUtils.h"
     15 #include "nsGkAtoms.h"
     16 #include "nsIContentInlines.h"
     17 #include "nsIURI.h"
     18 
     19 NS_IMPL_NS_NEW_SVG_ELEMENT(A)
     20 
     21 namespace mozilla::dom {
     22 
     23 JSObject* SVGAElement::WrapNode(JSContext* aCx,
     24                                JS::Handle<JSObject*> aGivenProto) {
     25  return SVGAElement_Binding::Wrap(aCx, this, aGivenProto);
     26 }
     27 
     28 SVGElement::StringInfo SVGAElement::sStringInfo[3] = {
     29    {nsGkAtoms::href, kNameSpaceID_None, true},
     30    {nsGkAtoms::href, kNameSpaceID_XLink, true},
     31    {nsGkAtoms::target, kNameSpaceID_None, true}};
     32 
     33 //----------------------------------------------------------------------
     34 // nsISupports methods
     35 
     36 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGAElement)
     37  NS_INTERFACE_MAP_ENTRY(Link)
     38 NS_INTERFACE_MAP_END_INHERITING(SVGAElementBase)
     39 
     40 NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGAElement, SVGAElementBase, mRelList)
     41 
     42 NS_IMPL_ADDREF_INHERITED(SVGAElement, SVGAElementBase)
     43 NS_IMPL_RELEASE_INHERITED(SVGAElement, SVGAElementBase)
     44 
     45 //----------------------------------------------------------------------
     46 // Implementation
     47 
     48 SVGAElement::SVGAElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     49    : SVGAElementBase(std::move(aNodeInfo)), Link(this) {}
     50 
     51 already_AddRefed<DOMSVGAnimatedString> SVGAElement::Href() {
     52  return mStringAttributes[HREF].IsExplicitlySet() ||
     53                 !mStringAttributes[XLINK_HREF].IsExplicitlySet()
     54             ? mStringAttributes[HREF].ToDOMAnimatedString(this)
     55             : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
     56 }
     57 
     58 //----------------------------------------------------------------------
     59 // nsINode methods
     60 
     61 void SVGAElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
     62  Element::GetEventTargetParent(aVisitor);
     63 
     64  GetEventTargetParentForLinks(aVisitor);
     65 }
     66 
     67 nsresult SVGAElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
     68  return PostHandleEventForLinks(aVisitor);
     69 }
     70 
     71 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGAElement)
     72 
     73 //----------------------------------------------------------------------
     74 
     75 already_AddRefed<DOMSVGAnimatedString> SVGAElement::Target() {
     76  return mStringAttributes[TARGET].ToDOMAnimatedString(this);
     77 }
     78 
     79 void SVGAElement::GetDownload(nsAString& aDownload) {
     80  GetAttr(nsGkAtoms::download, aDownload);
     81 }
     82 
     83 void SVGAElement::SetDownload(const nsAString& aDownload, ErrorResult& rv) {
     84  SetAttr(nsGkAtoms::download, aDownload, rv);
     85 }
     86 
     87 void SVGAElement::GetPing(nsAString& aPing) { GetAttr(nsGkAtoms::ping, aPing); }
     88 
     89 void SVGAElement::SetPing(const nsAString& aPing, ErrorResult& rv) {
     90  SetAttr(nsGkAtoms::ping, aPing, rv);
     91 }
     92 
     93 void SVGAElement::GetRel(nsAString& aRel) { GetAttr(nsGkAtoms::rel, aRel); }
     94 
     95 void SVGAElement::SetRel(const nsAString& aRel, ErrorResult& rv) {
     96  SetAttr(nsGkAtoms::rel, aRel, rv);
     97 }
     98 
     99 void SVGAElement::GetReferrerPolicy(nsAString& aPolicy) {
    100  GetEnumAttr(nsGkAtoms::referrerpolicy, "", aPolicy);
    101 }
    102 
    103 void SVGAElement::SetReferrerPolicy(const nsAString& aPolicy,
    104                                    mozilla::ErrorResult& rv) {
    105  SetAttr(nsGkAtoms::referrerpolicy, aPolicy, rv);
    106 }
    107 
    108 nsDOMTokenList* SVGAElement::RelList() {
    109  if (!mRelList) {
    110    mRelList =
    111        new nsDOMTokenList(this, nsGkAtoms::rel, sAnchorAndFormRelValues);
    112  }
    113  return mRelList;
    114 }
    115 
    116 void SVGAElement::GetHreflang(nsAString& aHreflang) {
    117  GetAttr(nsGkAtoms::hreflang, aHreflang);
    118 }
    119 
    120 void SVGAElement::SetHreflang(const nsAString& aHreflang,
    121                              mozilla::ErrorResult& rv) {
    122  SetAttr(nsGkAtoms::hreflang, aHreflang, rv);
    123 }
    124 
    125 void SVGAElement::GetType(nsAString& aType) { GetAttr(nsGkAtoms::type, aType); }
    126 
    127 void SVGAElement::SetType(const nsAString& aType, mozilla::ErrorResult& rv) {
    128  SetAttr(nsGkAtoms::type, aType, rv);
    129 }
    130 
    131 void SVGAElement::GetText(nsAString& aText, mozilla::ErrorResult& rv) const {
    132  if (NS_WARN_IF(
    133          !nsContentUtils::GetNodeTextContent(this, true, aText, fallible))) {
    134    rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    135  }
    136 }
    137 
    138 void SVGAElement::SetText(const nsAString& aText, mozilla::ErrorResult& rv) {
    139  rv = nsContentUtils::SetNodeTextContent(this, aText, false);
    140 }
    141 
    142 //----------------------------------------------------------------------
    143 // nsIContent methods
    144 
    145 nsresult SVGAElement::BindToTree(BindContext& aContext, nsINode& aParent) {
    146  nsresult rv = SVGAElementBase::BindToTree(aContext, aParent);
    147  NS_ENSURE_SUCCESS(rv, rv);
    148  Link::BindToTree(aContext);
    149  return NS_OK;
    150 }
    151 
    152 void SVGAElement::UnbindFromTree(UnbindContext& aContext) {
    153  SVGAElementBase::UnbindFromTree(aContext);
    154  // Without removing the link state we risk a dangling pointer
    155  // in the mStyledLinks hashtable
    156  Link::UnbindFromTree();
    157 }
    158 
    159 int32_t SVGAElement::TabIndexDefault() { return 0; }
    160 
    161 Focusable SVGAElement::IsFocusableWithoutStyle(IsFocusableFlags) {
    162  Focusable result;
    163  if (IsSVGFocusable(&result.mFocusable, &result.mTabIndex)) {
    164    return result;
    165  }
    166 
    167  if (!OwnerDoc()->LinkHandlingEnabled()) {
    168    return {};
    169  }
    170 
    171  // Links that are in an editable region should never be focusable, even if
    172  // they are in a contenteditable="false" region.
    173  if (nsContentUtils::IsNodeInEditableRegion(this)) {
    174    return {};
    175  }
    176 
    177  if (GetTabIndexAttrValue().isNothing()) {
    178    // check whether we're actually a link
    179    if (!IsLink()) {
    180      // Not tabbable or focusable without href (bug 17605), unless
    181      // forced to be via presence of nonnegative tabindex attribute
    182      return {};
    183    }
    184  }
    185  if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
    186    result.mTabIndex = -1;
    187  }
    188  return result;
    189 }
    190 
    191 bool SVGAElement::HasHref() const {
    192  // Currently our SMIL implementation does not modify the DOM attributes. Once
    193  // we implement the SVG 2 SMIL behaviour this can be removed.
    194  return mStringAttributes[HREF].IsExplicitlySet() ||
    195         mStringAttributes[XLINK_HREF].IsExplicitlySet();
    196 }
    197 
    198 already_AddRefed<nsIURI> SVGAElement::GetHrefURI() const {
    199  // Optimization: check for href first for early return
    200  bool useBareHref = mStringAttributes[HREF].IsExplicitlySet();
    201  if (useBareHref || mStringAttributes[XLINK_HREF].IsExplicitlySet()) {
    202    // Get absolute URI
    203    nsAutoString str;
    204    const uint8_t idx = useBareHref ? HREF : XLINK_HREF;
    205    mStringAttributes[idx].GetAnimValue(str, this);
    206    nsCOMPtr<nsIURI> uri;
    207    nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), str,
    208                                              OwnerDoc(), GetBaseURI());
    209    return uri.forget();
    210  }
    211  return nullptr;
    212 }
    213 
    214 void SVGAElement::GetLinkTargetImpl(nsAString& aTarget) {
    215  mStringAttributes[TARGET].GetAnimValue(aTarget, this);
    216  if (aTarget.IsEmpty()) {
    217    static Element::AttrValuesArray sShowVals[] = {nsGkAtoms::_new,
    218                                                   nsGkAtoms::replace, nullptr};
    219 
    220    switch (FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show, sShowVals,
    221                            eCaseMatters)) {
    222      case 0:
    223        aTarget.AssignLiteral("_blank");
    224        return;
    225      case 1:
    226        return;
    227    }
    228    Document* ownerDoc = OwnerDoc();
    229    if (ownerDoc) {
    230      ownerDoc->GetBaseTarget(aTarget);
    231    }
    232  }
    233 }
    234 
    235 void SVGAElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
    236                               const nsAttrValue* aValue,
    237                               const nsAttrValue* aOldValue,
    238                               nsIPrincipal* aMaybeScriptedPrincipal,
    239                               bool aNotify) {
    240  if (aName == nsGkAtoms::href && (aNameSpaceID == kNameSpaceID_XLink ||
    241                                   aNameSpaceID == kNameSpaceID_None)) {
    242    // We can't assume that null aValue means we no longer have an href, because
    243    // we could be unsetting xlink:href but still have a null-namespace href, or
    244    // vice versa.  But we can fast-path the case when we _do_ have a new value.
    245    Link::ResetLinkState(aNotify, aValue || Link::ElementHasHref());
    246  }
    247 
    248  return SVGAElementBase::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue,
    249                                       aMaybeScriptedPrincipal, aNotify);
    250 }
    251 
    252 //----------------------------------------------------------------------
    253 // SVGElement methods
    254 
    255 SVGElement::StringAttributesInfo SVGAElement::GetStringInfo() {
    256  return StringAttributesInfo(mStringAttributes, sStringInfo,
    257                              std::size(sStringInfo));
    258 }
    259 
    260 void SVGAElement::DidAnimateAttribute(int32_t aNameSpaceID,
    261                                      nsAtom* aAttribute) {
    262  if ((aNameSpaceID == kNameSpaceID_None ||
    263       aNameSpaceID == kNameSpaceID_XLink) &&
    264      aAttribute == nsGkAtoms::href) {
    265    Link::ResetLinkState(true, Link::ElementHasHref());
    266  }
    267  SVGAElementBase::DidAnimateAttribute(aNameSpaceID, aAttribute);
    268 }
    269 
    270 }  // namespace mozilla::dom