Coverage Report

Created: 2018-09-25 14:53

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