|
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/. */ |
|
5 |
|
6 /* |
|
7 * A class for managing namespace IDs and mapping back and forth |
|
8 * between namespace IDs and namespace URIs. |
|
9 */ |
|
10 |
|
11 #include "nsNameSpaceManager.h" |
|
12 |
|
13 #include "nscore.h" |
|
14 #include "nsAutoPtr.h" |
|
15 #include "nsINodeInfo.h" |
|
16 #include "nsCOMArray.h" |
|
17 #include "nsContentCreatorFunctions.h" |
|
18 #include "nsString.h" |
|
19 #include "nsINodeInfo.h" |
|
20 #include "mozilla/ClearOnShutdown.h" |
|
21 #include "mozilla/dom/XBLChildrenElement.h" |
|
22 #include "mozilla/dom/Element.h" |
|
23 |
|
24 using namespace mozilla; |
|
25 using namespace mozilla::dom; |
|
26 |
|
27 #define kXMLNSNameSpaceURI "http://www.w3.org/2000/xmlns/" |
|
28 #define kXMLNameSpaceURI "http://www.w3.org/XML/1998/namespace" |
|
29 #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml" |
|
30 #define kXLinkNameSpaceURI "http://www.w3.org/1999/xlink" |
|
31 #define kXSLTNameSpaceURI "http://www.w3.org/1999/XSL/Transform" |
|
32 #define kXBLNameSpaceURI "http://www.mozilla.org/xbl" |
|
33 #define kMathMLNameSpaceURI "http://www.w3.org/1998/Math/MathML" |
|
34 #define kRDFNameSpaceURI "http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|
35 #define kXULNameSpaceURI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
36 #define kSVGNameSpaceURI "http://www.w3.org/2000/svg" |
|
37 |
|
38 StaticAutoPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance; |
|
39 |
|
40 /* static */ nsNameSpaceManager* |
|
41 nsNameSpaceManager::GetInstance() { |
|
42 if (!sInstance) { |
|
43 sInstance = new nsNameSpaceManager(); |
|
44 if (sInstance->Init()) { |
|
45 ClearOnShutdown(&sInstance); |
|
46 } else { |
|
47 delete sInstance; |
|
48 sInstance = nullptr; |
|
49 } |
|
50 } |
|
51 |
|
52 return sInstance; |
|
53 } |
|
54 |
|
55 bool nsNameSpaceManager::Init() |
|
56 { |
|
57 nsresult rv; |
|
58 #define REGISTER_NAMESPACE(uri, id) \ |
|
59 rv = AddNameSpace(NS_LITERAL_STRING(uri), id); \ |
|
60 NS_ENSURE_SUCCESS(rv, false) |
|
61 |
|
62 // Need to be ordered according to ID. |
|
63 REGISTER_NAMESPACE(kXMLNSNameSpaceURI, kNameSpaceID_XMLNS); |
|
64 REGISTER_NAMESPACE(kXMLNameSpaceURI, kNameSpaceID_XML); |
|
65 REGISTER_NAMESPACE(kXHTMLNameSpaceURI, kNameSpaceID_XHTML); |
|
66 REGISTER_NAMESPACE(kXLinkNameSpaceURI, kNameSpaceID_XLink); |
|
67 REGISTER_NAMESPACE(kXSLTNameSpaceURI, kNameSpaceID_XSLT); |
|
68 REGISTER_NAMESPACE(kXBLNameSpaceURI, kNameSpaceID_XBL); |
|
69 REGISTER_NAMESPACE(kMathMLNameSpaceURI, kNameSpaceID_MathML); |
|
70 REGISTER_NAMESPACE(kRDFNameSpaceURI, kNameSpaceID_RDF); |
|
71 REGISTER_NAMESPACE(kXULNameSpaceURI, kNameSpaceID_XUL); |
|
72 REGISTER_NAMESPACE(kSVGNameSpaceURI, kNameSpaceID_SVG); |
|
73 |
|
74 #undef REGISTER_NAMESPACE |
|
75 |
|
76 return true; |
|
77 } |
|
78 |
|
79 nsresult |
|
80 nsNameSpaceManager::RegisterNameSpace(const nsAString& aURI, |
|
81 int32_t& aNameSpaceID) |
|
82 { |
|
83 if (aURI.IsEmpty()) { |
|
84 aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details |
|
85 |
|
86 return NS_OK; |
|
87 } |
|
88 |
|
89 nsresult rv = NS_OK; |
|
90 if (!mURIToIDTable.Get(&aURI, &aNameSpaceID)) { |
|
91 aNameSpaceID = mURIArray.Length() + 1; // id is index + 1 |
|
92 |
|
93 rv = AddNameSpace(aURI, aNameSpaceID); |
|
94 if (NS_FAILED(rv)) { |
|
95 aNameSpaceID = kNameSpaceID_Unknown; |
|
96 } |
|
97 } |
|
98 |
|
99 NS_POSTCONDITION(aNameSpaceID >= -1, "Bogus namespace ID"); |
|
100 |
|
101 return rv; |
|
102 } |
|
103 |
|
104 nsresult |
|
105 nsNameSpaceManager::GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI) |
|
106 { |
|
107 NS_PRECONDITION(aNameSpaceID >= 0, "Bogus namespace ID"); |
|
108 |
|
109 int32_t index = aNameSpaceID - 1; // id is index + 1 |
|
110 if (index < 0 || index >= int32_t(mURIArray.Length())) { |
|
111 aURI.Truncate(); |
|
112 |
|
113 return NS_ERROR_ILLEGAL_VALUE; |
|
114 } |
|
115 |
|
116 aURI = *mURIArray.ElementAt(index); |
|
117 |
|
118 return NS_OK; |
|
119 } |
|
120 |
|
121 int32_t |
|
122 nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI) |
|
123 { |
|
124 if (aURI.IsEmpty()) { |
|
125 return kNameSpaceID_None; // xmlns="", see bug 75700 for details |
|
126 } |
|
127 |
|
128 int32_t nameSpaceID; |
|
129 |
|
130 if (mURIToIDTable.Get(&aURI, &nameSpaceID)) { |
|
131 NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID"); |
|
132 return nameSpaceID; |
|
133 } |
|
134 |
|
135 return kNameSpaceID_Unknown; |
|
136 } |
|
137 |
|
138 nsresult |
|
139 NS_NewElement(Element** aResult, |
|
140 already_AddRefed<nsINodeInfo>&& aNodeInfo, |
|
141 FromParser aFromParser) |
|
142 { |
|
143 nsCOMPtr<nsINodeInfo> ni = aNodeInfo; |
|
144 int32_t ns = ni->NamespaceID(); |
|
145 if (ns == kNameSpaceID_XHTML) { |
|
146 return NS_NewHTMLElement(aResult, ni.forget(), aFromParser); |
|
147 } |
|
148 #ifdef MOZ_XUL |
|
149 if (ns == kNameSpaceID_XUL) { |
|
150 return NS_NewXULElement(aResult, ni.forget()); |
|
151 } |
|
152 #endif |
|
153 if (ns == kNameSpaceID_MathML) { |
|
154 return NS_NewMathMLElement(aResult, ni.forget()); |
|
155 } |
|
156 if (ns == kNameSpaceID_SVG) { |
|
157 return NS_NewSVGElement(aResult, ni.forget(), aFromParser); |
|
158 } |
|
159 if (ns == kNameSpaceID_XBL && ni->Equals(nsGkAtoms::children)) { |
|
160 NS_ADDREF(*aResult = new XBLChildrenElement(ni.forget())); |
|
161 return NS_OK; |
|
162 } |
|
163 |
|
164 return NS_NewXMLElement(aResult, ni.forget()); |
|
165 } |
|
166 |
|
167 bool |
|
168 nsNameSpaceManager::HasElementCreator(int32_t aNameSpaceID) |
|
169 { |
|
170 return aNameSpaceID == kNameSpaceID_XHTML || |
|
171 #ifdef MOZ_XUL |
|
172 aNameSpaceID == kNameSpaceID_XUL || |
|
173 #endif |
|
174 aNameSpaceID == kNameSpaceID_MathML || |
|
175 aNameSpaceID == kNameSpaceID_SVG || |
|
176 false; |
|
177 } |
|
178 |
|
179 nsresult nsNameSpaceManager::AddNameSpace(const nsAString& aURI, |
|
180 const int32_t aNameSpaceID) |
|
181 { |
|
182 if (aNameSpaceID < 0) { |
|
183 // We've wrapped... Can't do anything else here; just bail. |
|
184 return NS_ERROR_OUT_OF_MEMORY; |
|
185 } |
|
186 |
|
187 NS_ASSERTION(aNameSpaceID - 1 == (int32_t) mURIArray.Length(), |
|
188 "BAD! AddNameSpace not called in right order!"); |
|
189 |
|
190 nsString* uri = new nsString(aURI); |
|
191 if (!uri || !mURIArray.AppendElement(uri)) { |
|
192 delete uri; |
|
193 return NS_ERROR_OUT_OF_MEMORY; |
|
194 } |
|
195 |
|
196 mURIToIDTable.Put(uri, aNameSpaceID); |
|
197 |
|
198 return NS_OK; |
|
199 } |