dom/xslt/xpath/XPathEvaluator.cpp

changeset 0
6474c204b198
     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

mercurial