tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

XPathEvaluator.cpp (5792B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      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 
      8 #include <utility>
      9 
     10 #include "XPathResult.h"
     11 #include "mozilla/dom/BindingUtils.h"
     12 #include "mozilla/dom/Document.h"
     13 #include "mozilla/dom/XPathEvaluatorBinding.h"
     14 #include "mozilla/dom/XPathExpression.h"
     15 #include "mozilla/dom/XPathNSResolverBinding.h"
     16 #include "nsAtom.h"
     17 #include "nsCOMPtr.h"
     18 #include "nsContentUtils.h"
     19 #include "nsDOMString.h"
     20 #include "nsError.h"
     21 #include "nsNameSpaceManager.h"
     22 #include "txExpr.h"
     23 #include "txExprParser.h"
     24 #include "txIXPathContext.h"
     25 #include "txURIUtils.h"
     26 
     27 namespace mozilla::dom {
     28 
     29 // txIParseContext implementation
     30 class XPathEvaluatorParseContext : public txIParseContext {
     31 public:
     32  XPathEvaluatorParseContext(XPathNSResolver* aResolver, bool aIsCaseSensitive)
     33      : mResolver(aResolver),
     34        mResolverNode(nullptr),
     35        mLastError(NS_OK),
     36        mIsCaseSensitive(aIsCaseSensitive) {}
     37  XPathEvaluatorParseContext(nsINode* aResolver, bool aIsCaseSensitive)
     38      : mResolver(nullptr),
     39        mResolverNode(aResolver),
     40        mLastError(NS_OK),
     41        mIsCaseSensitive(aIsCaseSensitive) {}
     42 
     43  nsresult getError() { return mLastError; }
     44 
     45  int32_t resolveNamespacePrefix(nsAtom* aPrefix) override;
     46  nsresult resolveFunctionCall(nsAtom* aName, int32_t aID,
     47                               FunctionCall** aFunction) override;
     48  bool caseInsensitiveNameTests() override;
     49  void SetErrorOffset(uint32_t aOffset) override;
     50 
     51 private:
     52  XPathNSResolver* mResolver;
     53  nsINode* mResolverNode;
     54  nsresult mLastError;
     55  bool mIsCaseSensitive;
     56 };
     57 
     58 XPathEvaluator::XPathEvaluator(Document* aDocument) : mDocument(aDocument) {}
     59 
     60 XPathEvaluator::~XPathEvaluator() = default;
     61 
     62 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
     63    const nsAString& aExpression, XPathNSResolver* aResolver,
     64    ErrorResult& aRv) {
     65  nsCOMPtr<Document> doc(mDocument);
     66  XPathEvaluatorParseContext pContext(aResolver,
     67                                      !(doc && doc->IsHTMLDocument()));
     68  return CreateExpression(aExpression, &pContext, doc, aRv);
     69 }
     70 
     71 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
     72    const nsAString& aExpression, nsINode* aResolver, ErrorResult& aRv) {
     73  nsCOMPtr<Document> doc(mDocument);
     74  XPathEvaluatorParseContext pContext(aResolver,
     75                                      !(doc && doc->IsHTMLDocument()));
     76  return CreateExpression(aExpression, &pContext, doc, aRv);
     77 }
     78 
     79 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
     80    const nsAString& aExpression, txIParseContext* aContext,
     81    Document* aDocument, ErrorResult& aRv) {
     82  if (!mRecycler) {
     83    mRecycler = new txResultRecycler;
     84  }
     85 
     86  UniquePtr<Expr> expression;
     87  aRv = txExprParser::createExpr(PromiseFlatString(aExpression), aContext,
     88                                 getter_Transfers(expression));
     89  if (aRv.Failed()) {
     90    if (!aRv.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR)) {
     91      aRv.SuppressException();
     92      aRv.ThrowSyntaxError("The expression is not a legal expression");
     93    }
     94 
     95    return nullptr;
     96  }
     97 
     98  return MakeUnique<XPathExpression>(std::move(expression), mRecycler,
     99                                     aDocument);
    100 }
    101 
    102 bool XPathEvaluator::WrapObject(JSContext* aCx,
    103                                JS::Handle<JSObject*> aGivenProto,
    104                                JS::MutableHandle<JSObject*> aReflector) {
    105  return dom::XPathEvaluator_Binding::Wrap(aCx, this, aGivenProto, aReflector);
    106 }
    107 
    108 /* static */
    109 UniquePtr<XPathEvaluator> XPathEvaluator::Constructor(
    110    const GlobalObject& aGlobal) {
    111  return MakeUnique<XPathEvaluator>(nullptr);
    112 }
    113 
    114 already_AddRefed<XPathResult> XPathEvaluator::Evaluate(
    115    JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode,
    116    XPathNSResolver* aResolver, uint16_t aType, JS::Handle<JSObject*> aResult,
    117    ErrorResult& rv) {
    118  UniquePtr<XPathExpression> expression(
    119      CreateExpression(aExpression, aResolver, rv));
    120  if (rv.Failed()) {
    121    return nullptr;
    122  }
    123  return expression->Evaluate(aCx, aContextNode, aType, aResult, rv);
    124 }
    125 
    126 /*
    127 * Implementation of txIParseContext private to XPathEvaluator, based on a
    128 * XPathNSResolver
    129 */
    130 
    131 int32_t XPathEvaluatorParseContext::resolveNamespacePrefix(nsAtom* aPrefix) {
    132  if (!mResolver && !mResolverNode) {
    133    return kNameSpaceID_Unknown;
    134  }
    135 
    136  nsAutoString prefix;
    137  if (aPrefix) {
    138    aPrefix->ToString(prefix);
    139  }
    140 
    141  nsAutoString ns;
    142  if (mResolver) {
    143    ErrorResult rv;
    144    mResolver->LookupNamespaceURI(prefix, ns, rv);
    145    if (rv.Failed()) {
    146      rv.SuppressException();
    147      return kNameSpaceID_Unknown;
    148    }
    149  } else {
    150    if (aPrefix == nsGkAtoms::xml) {
    151      ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
    152    } else {
    153      mResolverNode->LookupNamespaceURI(prefix, ns);
    154    }
    155  }
    156 
    157  if (DOMStringIsNull(ns)) {
    158    return kNameSpaceID_Unknown;
    159  }
    160 
    161  if (ns.IsEmpty()) {
    162    return kNameSpaceID_None;
    163  }
    164 
    165  // get the namespaceID for the URI
    166  int32_t id;
    167  return NS_SUCCEEDED(
    168             nsNameSpaceManager::GetInstance()->RegisterNameSpace(ns, id))
    169             ? id
    170             : kNameSpaceID_Unknown;
    171 }
    172 
    173 nsresult XPathEvaluatorParseContext::resolveFunctionCall(nsAtom* aName,
    174                                                         int32_t aID,
    175                                                         FunctionCall** aFn) {
    176  return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
    177 }
    178 
    179 bool XPathEvaluatorParseContext::caseInsensitiveNameTests() {
    180  return !mIsCaseSensitive;
    181 }
    182 
    183 void XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) {}
    184 
    185 }  // namespace mozilla::dom