|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 #include "mozilla/dom/XPathEvaluator.h" |
|
7 #include "nsCOMPtr.h" |
|
8 #include "nsIAtom.h" |
|
9 #include "nsXPathExpression.h" |
|
10 #include "nsXPathNSResolver.h" |
|
11 #include "nsXPathResult.h" |
|
12 #include "nsContentCID.h" |
|
13 #include "txExpr.h" |
|
14 #include "txExprParser.h" |
|
15 #include "nsError.h" |
|
16 #include "txURIUtils.h" |
|
17 #include "nsIDocument.h" |
|
18 #include "nsIDOMDocument.h" |
|
19 #include "nsDOMString.h" |
|
20 #include "nsNameSpaceManager.h" |
|
21 #include "nsContentUtils.h" |
|
22 #include "mozilla/dom/XPathEvaluatorBinding.h" |
|
23 |
|
24 extern nsresult |
|
25 TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID, |
|
26 nsIAtom *aName, nsISupports *aState, |
|
27 FunctionCall **aFunction); |
|
28 |
|
29 namespace mozilla { |
|
30 namespace dom { |
|
31 |
|
32 // txIParseContext implementation |
|
33 class XPathEvaluatorParseContext : public txIParseContext |
|
34 { |
|
35 public: |
|
36 XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, |
|
37 bool aIsCaseSensitive) |
|
38 : mResolver(aResolver), |
|
39 mLastError(NS_OK), |
|
40 mIsCaseSensitive(aIsCaseSensitive) |
|
41 { |
|
42 } |
|
43 |
|
44 nsresult getError() |
|
45 { |
|
46 return mLastError; |
|
47 } |
|
48 |
|
49 nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID); |
|
50 nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID, |
|
51 FunctionCall** aFunction); |
|
52 bool caseInsensitiveNameTests(); |
|
53 void SetErrorOffset(uint32_t aOffset); |
|
54 |
|
55 private: |
|
56 nsIDOMXPathNSResolver* mResolver; |
|
57 nsresult mLastError; |
|
58 bool mIsCaseSensitive; |
|
59 }; |
|
60 |
|
61 NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator) |
|
62 |
|
63 XPathEvaluator::XPathEvaluator(nsIDocument* aDocument) |
|
64 : mDocument(do_GetWeakReference(aDocument)) |
|
65 { |
|
66 } |
|
67 |
|
68 NS_IMETHODIMP |
|
69 XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, |
|
70 nsIDOMXPathNSResolver **aResult) |
|
71 { |
|
72 NS_ENSURE_ARG(aNodeResolver); |
|
73 if (!nsContentUtils::CanCallerAccess(aNodeResolver)) |
|
74 return NS_ERROR_DOM_SECURITY_ERR; |
|
75 |
|
76 *aResult = new nsXPathNSResolver(aNodeResolver); |
|
77 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); |
|
78 |
|
79 NS_ADDREF(*aResult); |
|
80 return NS_OK; |
|
81 } |
|
82 |
|
83 NS_IMETHODIMP |
|
84 XPathEvaluator::Evaluate(const nsAString & aExpression, |
|
85 nsIDOMNode *aContextNode, |
|
86 nsIDOMXPathNSResolver *aResolver, |
|
87 uint16_t aType, |
|
88 nsISupports *aInResult, |
|
89 nsISupports **aResult) |
|
90 { |
|
91 nsCOMPtr<nsIDOMXPathExpression> expression; |
|
92 nsresult rv = CreateExpression(aExpression, aResolver, |
|
93 getter_AddRefs(expression)); |
|
94 NS_ENSURE_SUCCESS(rv, rv); |
|
95 |
|
96 return expression->Evaluate(aContextNode, aType, aInResult, aResult); |
|
97 } |
|
98 |
|
99 |
|
100 NS_IMETHODIMP |
|
101 XPathEvaluator::CreateExpression(const nsAString & aExpression, |
|
102 nsIDOMXPathNSResolver *aResolver, |
|
103 nsIDOMXPathExpression **aResult) |
|
104 { |
|
105 nsresult rv; |
|
106 if (!mRecycler) { |
|
107 nsRefPtr<txResultRecycler> recycler = new txResultRecycler; |
|
108 NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY); |
|
109 |
|
110 rv = recycler->init(); |
|
111 NS_ENSURE_SUCCESS(rv, rv); |
|
112 |
|
113 mRecycler = recycler; |
|
114 } |
|
115 |
|
116 nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument); |
|
117 XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML())); |
|
118 |
|
119 nsAutoPtr<Expr> expression; |
|
120 rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext, |
|
121 getter_Transfers(expression)); |
|
122 if (NS_FAILED(rv)) { |
|
123 if (rv == NS_ERROR_DOM_NAMESPACE_ERR) { |
|
124 return NS_ERROR_DOM_NAMESPACE_ERR; |
|
125 } |
|
126 |
|
127 return NS_ERROR_DOM_INVALID_EXPRESSION_ERR; |
|
128 } |
|
129 |
|
130 nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument); |
|
131 |
|
132 *aResult = new nsXPathExpression(expression, mRecycler, document); |
|
133 if (!*aResult) { |
|
134 return NS_ERROR_OUT_OF_MEMORY; |
|
135 } |
|
136 |
|
137 NS_ADDREF(*aResult); |
|
138 return NS_OK; |
|
139 } |
|
140 |
|
141 JSObject* |
|
142 XPathEvaluator::WrapObject(JSContext* aCx) |
|
143 { |
|
144 return dom::XPathEvaluatorBinding::Wrap(aCx, this); |
|
145 } |
|
146 |
|
147 /* static */ |
|
148 already_AddRefed<XPathEvaluator> |
|
149 XPathEvaluator::Constructor(const GlobalObject& aGlobal, |
|
150 ErrorResult& rv) |
|
151 { |
|
152 nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr); |
|
153 return newObj.forget(); |
|
154 } |
|
155 |
|
156 already_AddRefed<nsIDOMXPathExpression> |
|
157 XPathEvaluator::CreateExpression(const nsAString& aExpression, |
|
158 nsIDOMXPathNSResolver* aResolver, |
|
159 ErrorResult& rv) |
|
160 { |
|
161 nsCOMPtr<nsIDOMXPathExpression> expr; |
|
162 rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); |
|
163 return expr.forget(); |
|
164 } |
|
165 |
|
166 already_AddRefed<nsIDOMXPathNSResolver> |
|
167 XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, |
|
168 ErrorResult& rv) |
|
169 { |
|
170 nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver); |
|
171 nsCOMPtr<nsIDOMXPathNSResolver> res; |
|
172 rv = CreateNSResolver(nodeResolver, getter_AddRefs(res)); |
|
173 return res.forget(); |
|
174 } |
|
175 |
|
176 already_AddRefed<nsISupports> |
|
177 XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, |
|
178 nsIDOMXPathNSResolver* aResolver, uint16_t aType, |
|
179 nsISupports* aResult, ErrorResult& rv) |
|
180 { |
|
181 nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode); |
|
182 nsCOMPtr<nsISupports> res; |
|
183 rv = Evaluate(aExpression, contextNode, aResolver, aType, |
|
184 aResult, getter_AddRefs(res)); |
|
185 return res.forget(); |
|
186 } |
|
187 |
|
188 |
|
189 /* |
|
190 * Implementation of txIParseContext private to XPathEvaluator, based on a |
|
191 * nsIDOMXPathNSResolver |
|
192 */ |
|
193 |
|
194 nsresult XPathEvaluatorParseContext::resolveNamespacePrefix |
|
195 (nsIAtom* aPrefix, int32_t& aID) |
|
196 { |
|
197 aID = kNameSpaceID_Unknown; |
|
198 |
|
199 if (!mResolver) { |
|
200 return NS_ERROR_DOM_NAMESPACE_ERR; |
|
201 } |
|
202 |
|
203 nsAutoString prefix; |
|
204 if (aPrefix) { |
|
205 aPrefix->ToString(prefix); |
|
206 } |
|
207 |
|
208 nsVoidableString ns; |
|
209 nsresult rv = mResolver->LookupNamespaceURI(prefix, ns); |
|
210 NS_ENSURE_SUCCESS(rv, rv); |
|
211 |
|
212 if (DOMStringIsNull(ns)) { |
|
213 return NS_ERROR_DOM_NAMESPACE_ERR; |
|
214 } |
|
215 |
|
216 if (ns.IsEmpty()) { |
|
217 aID = kNameSpaceID_None; |
|
218 |
|
219 return NS_OK; |
|
220 } |
|
221 |
|
222 // get the namespaceID for the URI |
|
223 return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID); |
|
224 } |
|
225 |
|
226 nsresult |
|
227 XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, |
|
228 int32_t aID, |
|
229 FunctionCall** aFn) |
|
230 { |
|
231 return NS_ERROR_XPATH_UNKNOWN_FUNCTION; |
|
232 } |
|
233 |
|
234 bool XPathEvaluatorParseContext::caseInsensitiveNameTests() |
|
235 { |
|
236 return !mIsCaseSensitive; |
|
237 } |
|
238 |
|
239 void |
|
240 XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) |
|
241 { |
|
242 } |
|
243 |
|
244 } // namespace dom |
|
245 } // namespace mozilla |