1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xslt/xpath/XPathEvaluator.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/dom/XPathEvaluator.h" 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsIAtom.h" 1.12 +#include "nsXPathExpression.h" 1.13 +#include "nsXPathNSResolver.h" 1.14 +#include "nsXPathResult.h" 1.15 +#include "nsContentCID.h" 1.16 +#include "txExpr.h" 1.17 +#include "txExprParser.h" 1.18 +#include "nsError.h" 1.19 +#include "txURIUtils.h" 1.20 +#include "nsIDocument.h" 1.21 +#include "nsIDOMDocument.h" 1.22 +#include "nsDOMString.h" 1.23 +#include "nsNameSpaceManager.h" 1.24 +#include "nsContentUtils.h" 1.25 +#include "mozilla/dom/XPathEvaluatorBinding.h" 1.26 + 1.27 +extern nsresult 1.28 +TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID, 1.29 + nsIAtom *aName, nsISupports *aState, 1.30 + FunctionCall **aFunction); 1.31 + 1.32 +namespace mozilla { 1.33 +namespace dom { 1.34 + 1.35 +// txIParseContext implementation 1.36 +class XPathEvaluatorParseContext : public txIParseContext 1.37 +{ 1.38 +public: 1.39 + XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, 1.40 + bool aIsCaseSensitive) 1.41 + : mResolver(aResolver), 1.42 + mLastError(NS_OK), 1.43 + mIsCaseSensitive(aIsCaseSensitive) 1.44 + { 1.45 + } 1.46 + 1.47 + nsresult getError() 1.48 + { 1.49 + return mLastError; 1.50 + } 1.51 + 1.52 + nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID); 1.53 + nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID, 1.54 + FunctionCall** aFunction); 1.55 + bool caseInsensitiveNameTests(); 1.56 + void SetErrorOffset(uint32_t aOffset); 1.57 + 1.58 +private: 1.59 + nsIDOMXPathNSResolver* mResolver; 1.60 + nsresult mLastError; 1.61 + bool mIsCaseSensitive; 1.62 +}; 1.63 + 1.64 +NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator) 1.65 + 1.66 +XPathEvaluator::XPathEvaluator(nsIDocument* aDocument) 1.67 + : mDocument(do_GetWeakReference(aDocument)) 1.68 +{ 1.69 +} 1.70 + 1.71 +NS_IMETHODIMP 1.72 +XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, 1.73 + nsIDOMXPathNSResolver **aResult) 1.74 +{ 1.75 + NS_ENSURE_ARG(aNodeResolver); 1.76 + if (!nsContentUtils::CanCallerAccess(aNodeResolver)) 1.77 + return NS_ERROR_DOM_SECURITY_ERR; 1.78 + 1.79 + *aResult = new nsXPathNSResolver(aNodeResolver); 1.80 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.81 + 1.82 + NS_ADDREF(*aResult); 1.83 + return NS_OK; 1.84 +} 1.85 + 1.86 +NS_IMETHODIMP 1.87 +XPathEvaluator::Evaluate(const nsAString & aExpression, 1.88 + nsIDOMNode *aContextNode, 1.89 + nsIDOMXPathNSResolver *aResolver, 1.90 + uint16_t aType, 1.91 + nsISupports *aInResult, 1.92 + nsISupports **aResult) 1.93 +{ 1.94 + nsCOMPtr<nsIDOMXPathExpression> expression; 1.95 + nsresult rv = CreateExpression(aExpression, aResolver, 1.96 + getter_AddRefs(expression)); 1.97 + NS_ENSURE_SUCCESS(rv, rv); 1.98 + 1.99 + return expression->Evaluate(aContextNode, aType, aInResult, aResult); 1.100 +} 1.101 + 1.102 + 1.103 +NS_IMETHODIMP 1.104 +XPathEvaluator::CreateExpression(const nsAString & aExpression, 1.105 + nsIDOMXPathNSResolver *aResolver, 1.106 + nsIDOMXPathExpression **aResult) 1.107 +{ 1.108 + nsresult rv; 1.109 + if (!mRecycler) { 1.110 + nsRefPtr<txResultRecycler> recycler = new txResultRecycler; 1.111 + NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY); 1.112 + 1.113 + rv = recycler->init(); 1.114 + NS_ENSURE_SUCCESS(rv, rv); 1.115 + 1.116 + mRecycler = recycler; 1.117 + } 1.118 + 1.119 + nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument); 1.120 + XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML())); 1.121 + 1.122 + nsAutoPtr<Expr> expression; 1.123 + rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext, 1.124 + getter_Transfers(expression)); 1.125 + if (NS_FAILED(rv)) { 1.126 + if (rv == NS_ERROR_DOM_NAMESPACE_ERR) { 1.127 + return NS_ERROR_DOM_NAMESPACE_ERR; 1.128 + } 1.129 + 1.130 + return NS_ERROR_DOM_INVALID_EXPRESSION_ERR; 1.131 + } 1.132 + 1.133 + nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument); 1.134 + 1.135 + *aResult = new nsXPathExpression(expression, mRecycler, document); 1.136 + if (!*aResult) { 1.137 + return NS_ERROR_OUT_OF_MEMORY; 1.138 + } 1.139 + 1.140 + NS_ADDREF(*aResult); 1.141 + return NS_OK; 1.142 +} 1.143 + 1.144 +JSObject* 1.145 +XPathEvaluator::WrapObject(JSContext* aCx) 1.146 +{ 1.147 + return dom::XPathEvaluatorBinding::Wrap(aCx, this); 1.148 +} 1.149 + 1.150 +/* static */ 1.151 +already_AddRefed<XPathEvaluator> 1.152 +XPathEvaluator::Constructor(const GlobalObject& aGlobal, 1.153 + ErrorResult& rv) 1.154 +{ 1.155 + nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr); 1.156 + return newObj.forget(); 1.157 +} 1.158 + 1.159 +already_AddRefed<nsIDOMXPathExpression> 1.160 +XPathEvaluator::CreateExpression(const nsAString& aExpression, 1.161 + nsIDOMXPathNSResolver* aResolver, 1.162 + ErrorResult& rv) 1.163 +{ 1.164 + nsCOMPtr<nsIDOMXPathExpression> expr; 1.165 + rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); 1.166 + return expr.forget(); 1.167 +} 1.168 + 1.169 +already_AddRefed<nsIDOMXPathNSResolver> 1.170 +XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, 1.171 + ErrorResult& rv) 1.172 +{ 1.173 + nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver); 1.174 + nsCOMPtr<nsIDOMXPathNSResolver> res; 1.175 + rv = CreateNSResolver(nodeResolver, getter_AddRefs(res)); 1.176 + return res.forget(); 1.177 +} 1.178 + 1.179 +already_AddRefed<nsISupports> 1.180 +XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, 1.181 + nsIDOMXPathNSResolver* aResolver, uint16_t aType, 1.182 + nsISupports* aResult, ErrorResult& rv) 1.183 +{ 1.184 + nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode); 1.185 + nsCOMPtr<nsISupports> res; 1.186 + rv = Evaluate(aExpression, contextNode, aResolver, aType, 1.187 + aResult, getter_AddRefs(res)); 1.188 + return res.forget(); 1.189 +} 1.190 + 1.191 + 1.192 +/* 1.193 + * Implementation of txIParseContext private to XPathEvaluator, based on a 1.194 + * nsIDOMXPathNSResolver 1.195 + */ 1.196 + 1.197 +nsresult XPathEvaluatorParseContext::resolveNamespacePrefix 1.198 + (nsIAtom* aPrefix, int32_t& aID) 1.199 +{ 1.200 + aID = kNameSpaceID_Unknown; 1.201 + 1.202 + if (!mResolver) { 1.203 + return NS_ERROR_DOM_NAMESPACE_ERR; 1.204 + } 1.205 + 1.206 + nsAutoString prefix; 1.207 + if (aPrefix) { 1.208 + aPrefix->ToString(prefix); 1.209 + } 1.210 + 1.211 + nsVoidableString ns; 1.212 + nsresult rv = mResolver->LookupNamespaceURI(prefix, ns); 1.213 + NS_ENSURE_SUCCESS(rv, rv); 1.214 + 1.215 + if (DOMStringIsNull(ns)) { 1.216 + return NS_ERROR_DOM_NAMESPACE_ERR; 1.217 + } 1.218 + 1.219 + if (ns.IsEmpty()) { 1.220 + aID = kNameSpaceID_None; 1.221 + 1.222 + return NS_OK; 1.223 + } 1.224 + 1.225 + // get the namespaceID for the URI 1.226 + return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID); 1.227 +} 1.228 + 1.229 +nsresult 1.230 +XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, 1.231 + int32_t aID, 1.232 + FunctionCall** aFn) 1.233 +{ 1.234 + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; 1.235 +} 1.236 + 1.237 +bool XPathEvaluatorParseContext::caseInsensitiveNameTests() 1.238 +{ 1.239 + return !mIsCaseSensitive; 1.240 +} 1.241 + 1.242 +void 1.243 +XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) 1.244 +{ 1.245 +} 1.246 + 1.247 +} // namespace dom 1.248 +} // namespace mozilla