diff -r 000000000000 -r 6474c204b198 dom/xslt/xpath/XPathEvaluator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/xslt/xpath/XPathEvaluator.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/XPathEvaluator.h" +#include "nsCOMPtr.h" +#include "nsIAtom.h" +#include "nsXPathExpression.h" +#include "nsXPathNSResolver.h" +#include "nsXPathResult.h" +#include "nsContentCID.h" +#include "txExpr.h" +#include "txExprParser.h" +#include "nsError.h" +#include "txURIUtils.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsDOMString.h" +#include "nsNameSpaceManager.h" +#include "nsContentUtils.h" +#include "mozilla/dom/XPathEvaluatorBinding.h" + +extern nsresult +TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID, + nsIAtom *aName, nsISupports *aState, + FunctionCall **aFunction); + +namespace mozilla { +namespace dom { + +// txIParseContext implementation +class XPathEvaluatorParseContext : public txIParseContext +{ +public: + XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, + bool aIsCaseSensitive) + : mResolver(aResolver), + mLastError(NS_OK), + mIsCaseSensitive(aIsCaseSensitive) + { + } + + nsresult getError() + { + return mLastError; + } + + nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID); + nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID, + FunctionCall** aFunction); + bool caseInsensitiveNameTests(); + void SetErrorOffset(uint32_t aOffset); + +private: + nsIDOMXPathNSResolver* mResolver; + nsresult mLastError; + bool mIsCaseSensitive; +}; + +NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator) + +XPathEvaluator::XPathEvaluator(nsIDocument* aDocument) + : mDocument(do_GetWeakReference(aDocument)) +{ +} + +NS_IMETHODIMP +XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, + nsIDOMXPathNSResolver **aResult) +{ + NS_ENSURE_ARG(aNodeResolver); + if (!nsContentUtils::CanCallerAccess(aNodeResolver)) + return NS_ERROR_DOM_SECURITY_ERR; + + *aResult = new nsXPathNSResolver(aNodeResolver); + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(*aResult); + return NS_OK; +} + +NS_IMETHODIMP +XPathEvaluator::Evaluate(const nsAString & aExpression, + nsIDOMNode *aContextNode, + nsIDOMXPathNSResolver *aResolver, + uint16_t aType, + nsISupports *aInResult, + nsISupports **aResult) +{ + nsCOMPtr expression; + nsresult rv = CreateExpression(aExpression, aResolver, + getter_AddRefs(expression)); + NS_ENSURE_SUCCESS(rv, rv); + + return expression->Evaluate(aContextNode, aType, aInResult, aResult); +} + + +NS_IMETHODIMP +XPathEvaluator::CreateExpression(const nsAString & aExpression, + nsIDOMXPathNSResolver *aResolver, + nsIDOMXPathExpression **aResult) +{ + nsresult rv; + if (!mRecycler) { + nsRefPtr recycler = new txResultRecycler; + NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY); + + rv = recycler->init(); + NS_ENSURE_SUCCESS(rv, rv); + + mRecycler = recycler; + } + + nsCOMPtr doc = do_QueryReferent(mDocument); + XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML())); + + nsAutoPtr expression; + rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext, + getter_Transfers(expression)); + if (NS_FAILED(rv)) { + if (rv == NS_ERROR_DOM_NAMESPACE_ERR) { + return NS_ERROR_DOM_NAMESPACE_ERR; + } + + return NS_ERROR_DOM_INVALID_EXPRESSION_ERR; + } + + nsCOMPtr document = do_QueryReferent(mDocument); + + *aResult = new nsXPathExpression(expression, mRecycler, document); + if (!*aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(*aResult); + return NS_OK; +} + +JSObject* +XPathEvaluator::WrapObject(JSContext* aCx) +{ + return dom::XPathEvaluatorBinding::Wrap(aCx, this); +} + +/* static */ +already_AddRefed +XPathEvaluator::Constructor(const GlobalObject& aGlobal, + ErrorResult& rv) +{ + nsRefPtr newObj = new XPathEvaluator(nullptr); + return newObj.forget(); +} + +already_AddRefed +XPathEvaluator::CreateExpression(const nsAString& aExpression, + nsIDOMXPathNSResolver* aResolver, + ErrorResult& rv) +{ + nsCOMPtr expr; + rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); + return expr.forget(); +} + +already_AddRefed +XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, + ErrorResult& rv) +{ + nsCOMPtr nodeResolver = do_QueryInterface(aNodeResolver); + nsCOMPtr res; + rv = CreateNSResolver(nodeResolver, getter_AddRefs(res)); + return res.forget(); +} + +already_AddRefed +XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, + nsIDOMXPathNSResolver* aResolver, uint16_t aType, + nsISupports* aResult, ErrorResult& rv) +{ + nsCOMPtr contextNode = do_QueryInterface(aContextNode); + nsCOMPtr res; + rv = Evaluate(aExpression, contextNode, aResolver, aType, + aResult, getter_AddRefs(res)); + return res.forget(); +} + + +/* + * Implementation of txIParseContext private to XPathEvaluator, based on a + * nsIDOMXPathNSResolver + */ + +nsresult XPathEvaluatorParseContext::resolveNamespacePrefix + (nsIAtom* aPrefix, int32_t& aID) +{ + aID = kNameSpaceID_Unknown; + + if (!mResolver) { + return NS_ERROR_DOM_NAMESPACE_ERR; + } + + nsAutoString prefix; + if (aPrefix) { + aPrefix->ToString(prefix); + } + + nsVoidableString ns; + nsresult rv = mResolver->LookupNamespaceURI(prefix, ns); + NS_ENSURE_SUCCESS(rv, rv); + + if (DOMStringIsNull(ns)) { + return NS_ERROR_DOM_NAMESPACE_ERR; + } + + if (ns.IsEmpty()) { + aID = kNameSpaceID_None; + + return NS_OK; + } + + // get the namespaceID for the URI + return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID); +} + +nsresult +XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, + int32_t aID, + FunctionCall** aFn) +{ + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; +} + +bool XPathEvaluatorParseContext::caseInsensitiveNameTests() +{ + return !mIsCaseSensitive; +} + +void +XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) +{ +} + +} // namespace dom +} // namespace mozilla