tor-browser

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

nsNameSpaceManager.cpp (9670B)


      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 * A class for managing namespace IDs and mapping back and forth
      9 * between namespace IDs and namespace URIs.
     10 */
     11 
     12 #include "nsNameSpaceManager.h"
     13 
     14 #include "mozilla/ClearOnShutdown.h"
     15 #include "mozilla/Preferences.h"
     16 #include "mozilla/dom/Document.h"
     17 #include "mozilla/dom/Element.h"
     18 #include "mozilla/dom/NodeInfo.h"
     19 #include "nsAtom.h"
     20 #include "nsCOMArray.h"
     21 #include "nsContentCreatorFunctions.h"
     22 #include "nsGkAtoms.h"
     23 #include "nsString.h"
     24 #include "nscore.h"
     25 
     26 using namespace mozilla;
     27 using namespace mozilla::dom;
     28 
     29 static constexpr const char* kPrefSVGDisabled = "svg.disabled";
     30 static constexpr const char* kPrefMathMLDisabled = "mathml.disabled";
     31 static constexpr const char* kObservedNSPrefs[] = {kPrefMathMLDisabled,
     32                                                   kPrefSVGDisabled, nullptr};
     33 
     34 StaticRefPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance;
     35 
     36 /* static */
     37 nsNameSpaceManager* nsNameSpaceManager::GetInstance() {
     38  if (!sInstance) {
     39    sInstance = new nsNameSpaceManager();
     40    if (sInstance->Init()) {
     41      ClearOnShutdown(&sInstance);
     42    } else {
     43      delete sInstance;
     44      sInstance = nullptr;
     45    }
     46  }
     47 
     48  return sInstance;
     49 }
     50 
     51 bool nsNameSpaceManager::Init() {
     52  nsresult rv;
     53 #define REGISTER_NAMESPACE(uri, id)        \
     54  rv = AddNameSpace(dont_AddRef(uri), id); \
     55  NS_ENSURE_SUCCESS(rv, false)
     56 
     57 #define REGISTER_DISABLED_NAMESPACE(uri, id)       \
     58  rv = AddDisabledNameSpace(dont_AddRef(uri), id); \
     59  NS_ENSURE_SUCCESS(rv, false)
     60 
     61  mozilla::Preferences::RegisterCallbacks(nsNameSpaceManager::PrefChanged,
     62                                          kObservedNSPrefs, this);
     63 
     64  PrefChanged(nullptr);
     65 
     66  // Need to be ordered according to ID.
     67  MOZ_ASSERT(mURIArray.IsEmpty());
     68  REGISTER_NAMESPACE(nsGkAtoms::_empty, kNameSpaceID_None);
     69  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xmlns, kNameSpaceID_XMLNS);
     70  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xml, kNameSpaceID_XML);
     71  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xhtml, kNameSpaceID_XHTML);
     72  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xlink, kNameSpaceID_XLink);
     73  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xslt, kNameSpaceID_XSLT);
     74  REGISTER_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_MathML);
     75  REGISTER_NAMESPACE(nsGkAtoms::nsuri_rdf, kNameSpaceID_RDF);
     76  REGISTER_NAMESPACE(nsGkAtoms::nsuri_xul, kNameSpaceID_XUL);
     77  REGISTER_NAMESPACE(nsGkAtoms::nsuri_svg, kNameSpaceID_SVG);
     78  REGISTER_DISABLED_NAMESPACE(nsGkAtoms::nsuri_mathml,
     79                              kNameSpaceID_disabled_MathML);
     80  REGISTER_DISABLED_NAMESPACE(nsGkAtoms::nsuri_svg, kNameSpaceID_disabled_SVG);
     81 
     82 #undef REGISTER_NAMESPACE
     83 #undef REGISTER_DISABLED_NAMESPACE
     84 
     85  return true;
     86 }
     87 
     88 nsresult nsNameSpaceManager::RegisterNameSpace(const nsAString& aURI,
     89                                               int32_t& aNameSpaceID) {
     90  RefPtr<nsAtom> atom = NS_Atomize(aURI);
     91  return RegisterNameSpace(atom.forget(), aNameSpaceID);
     92 }
     93 
     94 nsresult nsNameSpaceManager::RegisterNameSpace(already_AddRefed<nsAtom> aURI,
     95                                               int32_t& aNameSpaceID) {
     96  RefPtr<nsAtom> atom = aURI;
     97  nsresult rv = NS_OK;
     98  if (atom == nsGkAtoms::_empty) {
     99    aNameSpaceID = kNameSpaceID_None;  // xmlns="", see bug 75700 for details
    100    return NS_OK;
    101  }
    102 
    103  if (!mURIToIDTable.Get(atom, &aNameSpaceID)) {
    104    aNameSpaceID = mURIArray.Length();
    105 
    106    rv = AddNameSpace(atom.forget(), aNameSpaceID);
    107    if (NS_FAILED(rv)) {
    108      aNameSpaceID = kNameSpaceID_Unknown;
    109    }
    110  }
    111 
    112  MOZ_ASSERT(aNameSpaceID >= -1, "Bogus namespace ID");
    113 
    114  return rv;
    115 }
    116 
    117 nsresult nsNameSpaceManager::GetNameSpaceURI(int32_t aNameSpaceID,
    118                                             nsAString& aURI) {
    119  MOZ_ASSERT(aNameSpaceID >= 0, "Bogus namespace ID");
    120 
    121  // We have historically treated GetNameSpaceURI calls for kNameSpaceID_None
    122  // as erroneous.
    123  if (aNameSpaceID <= 0 || aNameSpaceID >= int32_t(mURIArray.Length())) {
    124    aURI.Truncate();
    125 
    126    return NS_ERROR_ILLEGAL_VALUE;
    127  }
    128 
    129  mURIArray.ElementAt(aNameSpaceID)->ToString(aURI);
    130 
    131  return NS_OK;
    132 }
    133 
    134 int32_t nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI,
    135                                           bool aInChromeDoc) {
    136  if (aURI.IsEmpty()) {
    137    return kNameSpaceID_None;  // xmlns="", see bug 75700 for details
    138  }
    139 
    140  RefPtr<nsAtom> atom = NS_Atomize(aURI);
    141  return GetNameSpaceID(atom, aInChromeDoc);
    142 }
    143 
    144 int32_t nsNameSpaceManager::GetNameSpaceID(nsAtom* aURI, bool aInChromeDoc) {
    145  if (aURI == nsGkAtoms::_empty) {
    146    return kNameSpaceID_None;  // xmlns="", see bug 75700 for details
    147  }
    148 
    149  int32_t nameSpaceID;
    150  if (!aInChromeDoc && (mMathMLDisabled || mSVGDisabled) &&
    151      mDisabledURIToIDTable.Get(aURI, &nameSpaceID) &&
    152      ((mMathMLDisabled && kNameSpaceID_disabled_MathML == nameSpaceID) ||
    153       (mSVGDisabled && kNameSpaceID_disabled_SVG == nameSpaceID))) {
    154    MOZ_ASSERT(nameSpaceID >= 0, "Bogus namespace ID");
    155    return nameSpaceID;
    156  }
    157  if (mURIToIDTable.Get(aURI, &nameSpaceID)) {
    158    MOZ_ASSERT(nameSpaceID >= 0, "Bogus namespace ID");
    159    return nameSpaceID;
    160  }
    161 
    162  return kNameSpaceID_Unknown;
    163 }
    164 
    165 // static
    166 const char* nsNameSpaceManager::GetNameSpaceDisplayName(uint32_t aNameSpaceID) {
    167  static const char* kNSURIs[] = {"([none])", "(xmlns)", "(xml)",    "(xhtml)",
    168                                  "(XLink)",  "(XSLT)",  "(MathML)", "(RDF)",
    169                                  "(XUL)",    "(SVG)"};
    170  if (aNameSpaceID < std::size(kNSURIs)) {
    171    return kNSURIs[aNameSpaceID];
    172  }
    173  return "";
    174 }
    175 
    176 nsresult NS_NewElement(Element** aResult,
    177                       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
    178                       FromParser aFromParser, const nsAString* aIs) {
    179  RefPtr<nsAtom> isAtom = aIs ? NS_AtomizeMainThread(*aIs) : nullptr;
    180  return NS_NewElement(aResult, std::move(aNodeInfo), aFromParser, isAtom);
    181 }
    182 
    183 nsresult NS_NewElement(Element** aResult,
    184                       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
    185                       FromParser aFromParser, nsAtom* aIsAtom,
    186                       CustomElementDefinition* aDefinition) {
    187  RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
    188  int32_t ns = ni->NamespaceID();
    189  if (ns == kNameSpaceID_XHTML) {
    190    return NS_NewHTMLElement(aResult, ni.forget(), aFromParser, aIsAtom,
    191                             aDefinition);
    192  }
    193  if (ns == kNameSpaceID_XUL) {
    194    return NS_NewXULElement(aResult, ni.forget(), aFromParser, aIsAtom,
    195                            aDefinition);
    196  }
    197  if (ns == kNameSpaceID_MathML) {
    198    // If the mathml.disabled pref. is true, convert all MathML nodes into
    199    // disabled MathML nodes by swapping the namespace.
    200    if (ni->NodeInfoManager()->MathMLEnabled()) {
    201      return NS_NewMathMLElement(aResult, ni.forget());
    202    }
    203 
    204    RefPtr<mozilla::dom::NodeInfo> genericXMLNI =
    205        ni->NodeInfoManager()->GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(),
    206                                           kNameSpaceID_disabled_MathML,
    207                                           ni->NodeType(), ni->GetExtraName());
    208    return NS_NewXMLElement(aResult, genericXMLNI.forget());
    209  }
    210  if (ns == kNameSpaceID_SVG) {
    211    // If the svg.disabled pref. is true, convert all SVG nodes into
    212    // disabled SVG nodes by swapping the namespace.
    213    if (ni->NodeInfoManager()->SVGEnabled()) {
    214      return NS_NewSVGElement(aResult, ni.forget(), aFromParser);
    215    }
    216    RefPtr<mozilla::dom::NodeInfo> genericXMLNI =
    217        ni->NodeInfoManager()->GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(),
    218                                           kNameSpaceID_disabled_SVG,
    219                                           ni->NodeType(), ni->GetExtraName());
    220    return NS_NewXMLElement(aResult, genericXMLNI.forget());
    221  }
    222 
    223  return NS_NewXMLElement(aResult, ni.forget());
    224 }
    225 
    226 bool nsNameSpaceManager::HasElementCreator(int32_t aNameSpaceID) {
    227  return aNameSpaceID == kNameSpaceID_XHTML ||
    228         aNameSpaceID == kNameSpaceID_XUL ||
    229         aNameSpaceID == kNameSpaceID_MathML ||
    230         aNameSpaceID == kNameSpaceID_SVG || false;
    231 }
    232 
    233 nsresult nsNameSpaceManager::AddNameSpace(already_AddRefed<nsAtom> aURI,
    234                                          const int32_t aNameSpaceID) {
    235  RefPtr<nsAtom> uri = aURI;
    236  if (aNameSpaceID < 0) {
    237    // We've wrapped...  Can't do anything else here; just bail.
    238    return NS_ERROR_OUT_OF_MEMORY;
    239  }
    240 
    241  MOZ_ASSERT(aNameSpaceID == (int32_t)mURIArray.Length());
    242  mURIArray.AppendElement(uri.forget());
    243  mURIToIDTable.InsertOrUpdate(mURIArray.LastElement(), aNameSpaceID);
    244 
    245  return NS_OK;
    246 }
    247 
    248 nsresult nsNameSpaceManager::AddDisabledNameSpace(already_AddRefed<nsAtom> aURI,
    249                                                  const int32_t aNameSpaceID) {
    250  RefPtr<nsAtom> uri = aURI;
    251  if (aNameSpaceID < 0) {
    252    // We've wrapped...  Can't do anything else here; just bail.
    253    return NS_ERROR_OUT_OF_MEMORY;
    254  }
    255 
    256  MOZ_ASSERT(aNameSpaceID == (int32_t)mURIArray.Length());
    257  mURIArray.AppendElement(uri.forget());
    258  mDisabledURIToIDTable.InsertOrUpdate(mURIArray.LastElement(), aNameSpaceID);
    259 
    260  return NS_OK;
    261 }
    262 
    263 // static
    264 void nsNameSpaceManager::PrefChanged(const char* aPref, void* aSelf) {
    265  static_cast<nsNameSpaceManager*>(aSelf)->PrefChanged(aPref);
    266 }
    267 
    268 void nsNameSpaceManager::PrefChanged(const char* aPref) {
    269  mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
    270  mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled);
    271 }