tor-browser

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

Attr.cpp (8019B)


      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 /*
      8 * Implementation of DOM Core's Attr node.
      9 */
     10 
     11 #include "mozilla/dom/Attr.h"
     12 
     13 #include "NodeUbiReporting.h"
     14 #include "mozAutoDocUpdate.h"
     15 #include "mozilla/EventDispatcher.h"
     16 #include "mozilla/StaticPrefs_dom.h"
     17 #include "mozilla/dom/AttrBinding.h"
     18 #include "mozilla/dom/Document.h"
     19 #include "mozilla/dom/Element.h"
     20 #include "mozilla/dom/TrustedTypeUtils.h"
     21 #include "mozilla/dom/TrustedTypesConstants.h"
     22 #include "nsCOMArray.h"
     23 #include "nsContentCreatorFunctions.h"
     24 #include "nsDOMString.h"
     25 #include "nsError.h"
     26 #include "nsGkAtoms.h"
     27 #include "nsIContentInlines.h"
     28 #include "nsNameSpaceManager.h"
     29 #include "nsTextNode.h"
     30 #include "nsUnicharUtils.h"
     31 #include "nsWrapperCacheInlines.h"
     32 
     33 namespace mozilla::dom {
     34 
     35 //----------------------------------------------------------------------
     36 bool Attr::sInitialized;
     37 
     38 Attr::Attr(nsDOMAttributeMap* aAttrMap,
     39           already_AddRefed<dom::NodeInfo>&& aNodeInfo, const nsAString& aValue)
     40    : nsINode(std::move(aNodeInfo)), mAttrMap(aAttrMap), mValue(aValue) {
     41  MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
     42  MOZ_ASSERT(mNodeInfo->NodeType() == ATTRIBUTE_NODE, "Wrong nodeType");
     43 
     44  // We don't add a reference to our content. It will tell us
     45  // to drop our reference when it goes away.
     46 }
     47 
     48 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Attr)
     49 
     50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
     51  if (!nsINode::Traverse(tmp, cb)) {
     52    return NS_SUCCESS_INTERRUPTED_TRAVERSE;
     53  }
     54  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap)
     55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     56 
     57 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr)
     58  nsINode::Unlink(tmp);
     59  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap)
     60 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     61 
     62 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr)
     63  Element* ownerElement = tmp->GetElement();
     64  if (tmp->HasKnownLiveWrapper()) {
     65    if (ownerElement) {
     66      // The attribute owns the element via attribute map so we can
     67      // mark it when the attribute is certainly alive.
     68      mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement);
     69    }
     70    return true;
     71  }
     72  if (ownerElement &&
     73      mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) {
     74    return true;
     75  }
     76 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
     77 
     78 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr)
     79  return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
     80 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
     81 
     82 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr)
     83  return tmp->HasKnownLiveWrapper();
     84 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
     85 
     86 // QueryInterface implementation for Attr
     87 NS_INTERFACE_TABLE_HEAD(Attr)
     88  NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
     89  NS_INTERFACE_TABLE(Attr, nsINode, EventTarget)
     90  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr)
     91  NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
     92                                 new nsNodeSupportsWeakRefTearoff(this))
     93 NS_INTERFACE_MAP_END
     94 
     95 NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr)
     96 
     97 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE_AND_DESTROY(Attr,
     98                                                               LastRelease(),
     99                                                               Destroy())
    100 
    101 NS_IMPL_DOMARENA_DESTROY(Attr)
    102 
    103 void Attr::SetMap(nsDOMAttributeMap* aMap) {
    104  if (mAttrMap && !aMap && sInitialized) {
    105    // We're breaking a relationship with content and not getting a new one,
    106    // need to locally cache value. GetValue() does that.
    107    GetValue(mValue);
    108  }
    109 
    110  mAttrMap = aMap;
    111 }
    112 
    113 Element* Attr::GetElement() const {
    114  if (!mAttrMap) {
    115    return nullptr;
    116  }
    117  nsIContent* content = mAttrMap->GetContent();
    118  return content ? content->AsElement() : nullptr;
    119 }
    120 
    121 nsresult Attr::SetOwnerDocument(Document* aDocument) {
    122  NS_ASSERTION(aDocument, "Missing document");
    123 
    124  Document* doc = OwnerDoc();
    125  NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument");
    126  doc->RemoveAllPropertiesFor(this);
    127 
    128  RefPtr<dom::NodeInfo> newNodeInfo = aDocument->NodeInfoManager()->GetNodeInfo(
    129      mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
    130      mNodeInfo->NamespaceID(), ATTRIBUTE_NODE);
    131  NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
    132  mNodeInfo.swap(newNodeInfo);
    133 
    134  return NS_OK;
    135 }
    136 
    137 void Attr::GetName(nsAString& aName) { aName = NodeName(); }
    138 
    139 void Attr::GetValue(nsAString& aValue) {
    140  Element* element = GetElement();
    141  if (element) {
    142    RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
    143    element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
    144  } else {
    145    aValue = mValue;
    146  }
    147 }
    148 
    149 void Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal,
    150                    ErrorResult& aRv) {
    151  nsCOMPtr<Element> element = GetElement();
    152  if (!element) {
    153    mValue = aValue;
    154    return;
    155  }
    156 
    157  RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
    158 
    159  Maybe<nsAutoString> compliantStringHolder;
    160  const nsAString* compliantString =
    161      TrustedTypeUtils::GetTrustedTypesCompliantAttributeValue(
    162          *element, nameAtom, mNodeInfo->NamespaceID(), aValue,
    163          aTriggeringPrincipal, compliantStringHolder, aRv);
    164  if (aRv.Failed()) {
    165    return;
    166  }
    167 
    168  // After the GetTrustedTypesCompliantAttributeValue() call, the attribute may
    169  // have been detached or moved to another element so perform the check on
    170  // GetElement() again.
    171  SetValueInternal(*compliantString, aRv);
    172 }
    173 
    174 void Attr::SetValueInternal(const nsAString& aValue, ErrorResult& aRv) {
    175  Element* element = GetElement();
    176  if (!element) {
    177    mValue = aValue;
    178    return;
    179  }
    180 
    181  RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
    182  aRv = element->SetAttr(mNodeInfo->NamespaceID(), nameAtom,
    183                         mNodeInfo->GetPrefixAtom(), aValue, nullptr, true);
    184 }
    185 
    186 bool Attr::Specified() const { return true; }
    187 
    188 Element* Attr::GetOwnerElement() { return GetElement(); }
    189 
    190 void Attr::SetNodeValue(const nsAString& aNodeValue, ErrorResult& aError) {
    191  SetValue(aNodeValue, nullptr, aError);
    192 }
    193 
    194 void Attr::GetNodeValueInternal(nsAString& aNodeValue) { GetValue(aNodeValue); }
    195 
    196 void Attr::SetNodeValueInternal(const nsAString& aNodeValue,
    197                                ErrorResult& aError, MutationEffectOnScript) {
    198  SetValueInternal(aNodeValue, aError);
    199 }
    200 
    201 nsresult Attr::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const {
    202  nsAutoString value;
    203  const_cast<Attr*>(this)->GetValue(value);
    204  *aResult = new (aNodeInfo->NodeInfoManager())
    205      Attr(nullptr, do_AddRef(aNodeInfo), value);
    206 
    207  NS_ADDREF(*aResult);
    208 
    209  return NS_OK;
    210 }
    211 
    212 nsIURI* Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const {
    213  Element* parent = GetElement();
    214 
    215  return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI)
    216                : OwnerDoc()->GetBaseURI(aTryUseXHRDocBaseURI);
    217 }
    218 
    219 void Attr::SetTextContent(const nsAString& aTextContent,
    220                          nsIPrincipal* aSubjectPrincipal,
    221                          ErrorResult& aError) {
    222  SetValue(aTextContent, aSubjectPrincipal, aError);
    223 }
    224 
    225 void Attr::GetTextContentInternal(nsAString& aTextContent,
    226                                  OOMReporter& aError) {
    227  GetValue(aTextContent);
    228 }
    229 
    230 void Attr::SetTextContentInternal(const nsAString& aTextContent,
    231                                  nsIPrincipal* aSubjectPrincipal,
    232                                  ErrorResult& aError, MutationEffectOnScript) {
    233  SetValueInternal(aTextContent, aError);
    234 }
    235 
    236 void Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
    237  aVisitor.mCanHandle = true;
    238 }
    239 
    240 void Attr::Initialize() { sInitialized = true; }
    241 
    242 void Attr::Shutdown() { sInitialized = false; }
    243 
    244 JSObject* Attr::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
    245  return Attr_Binding::Wrap(aCx, this, aGivenProto);
    246 }
    247 
    248 void Attr::ConstructUbiNode(void* storage) {
    249  JS::ubi::Concrete<Attr>::construct(storage, this);
    250 }
    251 
    252 }  // namespace mozilla::dom