dom/xslt/xpath/XPathEvaluator.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:fd3a19de5fa7
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

mercurial