tor-browser

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

XPathExpression.cpp (6372B)


      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 "XPathExpression.h"
      7 
      8 #include <utility>
      9 
     10 #include "XPathResult.h"
     11 #include "mozilla/dom/BindingUtils.h"
     12 #include "mozilla/dom/Text.h"
     13 #include "mozilla/dom/XPathResultBinding.h"
     14 #include "nsError.h"
     15 #include "nsINode.h"
     16 #include "txExpr.h"
     17 #include "txExprResult.h"
     18 #include "txIXPathContext.h"
     19 #include "txURIUtils.h"
     20 #include "txXPathTreeWalker.h"
     21 
     22 namespace mozilla::dom {
     23 
     24 class MOZ_STACK_CLASS EvalContextImpl : public txIEvalContext {
     25 public:
     26  EvalContextImpl(const txXPathNode& aContextNode, uint32_t aContextPosition,
     27                  uint32_t aContextSize, txResultRecycler* aRecycler)
     28      : mContextNode(aContextNode),
     29        mContextPosition(aContextPosition),
     30        mContextSize(aContextSize),
     31        mLastError(NS_OK),
     32        mRecycler(aRecycler) {}
     33 
     34  nsresult getError() { return mLastError; }
     35 
     36  TX_DECL_EVAL_CONTEXT;
     37 
     38 private:
     39  const txXPathNode& mContextNode;
     40  uint32_t mContextPosition;
     41  uint32_t mContextSize;
     42  nsresult mLastError;
     43  RefPtr<txResultRecycler> mRecycler;
     44 };
     45 
     46 XPathExpression::XPathExpression(UniquePtr<Expr>&& aExpression,
     47                                 txResultRecycler* aRecycler,
     48                                 Document* aDocument)
     49    : mExpression(std::move(aExpression)),
     50      mRecycler(aRecycler),
     51      mDocument(do_GetWeakReference(aDocument)),
     52      mCheckDocument(aDocument != nullptr) {}
     53 
     54 XPathExpression::~XPathExpression() = default;
     55 
     56 already_AddRefed<XPathResult> XPathExpression::EvaluateWithContext(
     57    JSContext* aCx, nsINode& aContextNode, uint32_t aContextPosition,
     58    uint32_t aContextSize, uint16_t aType, JS::Handle<JSObject*> aInResult,
     59    ErrorResult& aRv) {
     60  RefPtr<XPathResult> inResult;
     61  if (aInResult) {
     62    nsresult rv = UNWRAP_OBJECT(XPathResult, aInResult, inResult);
     63    if (NS_FAILED(rv) && rv != NS_ERROR_XPC_BAD_CONVERT_JS) {
     64      aRv.Throw(rv);
     65      return nullptr;
     66    }
     67  }
     68 
     69  return EvaluateWithContext(aContextNode, aContextPosition, aContextSize,
     70                             aType, inResult, aRv);
     71 }
     72 
     73 already_AddRefed<XPathResult> XPathExpression::EvaluateWithContext(
     74    nsINode& aContextNode, uint32_t aContextPosition, uint32_t aContextSize,
     75    uint16_t aType, XPathResult* aInResult, ErrorResult& aRv) {
     76  if (aContextPosition > aContextSize) {
     77    aRv.Throw(NS_ERROR_FAILURE);
     78    return nullptr;
     79  }
     80 
     81  if (aType > XPathResult_Binding::FIRST_ORDERED_NODE_TYPE) {
     82    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     83    return nullptr;
     84  }
     85 
     86  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
     87      !nsContentUtils::CanCallerAccess(&aContextNode)) {
     88    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     89    return nullptr;
     90  }
     91 
     92  if (mCheckDocument) {
     93    nsCOMPtr<Document> doc = do_QueryReferent(mDocument);
     94    if (doc != aContextNode.OwnerDoc()) {
     95      aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
     96      return nullptr;
     97    }
     98  }
     99 
    100  uint16_t nodeType = aContextNode.NodeType();
    101 
    102  if (nodeType == nsINode::TEXT_NODE ||
    103      nodeType == nsINode::CDATA_SECTION_NODE) {
    104    Text* textNode = aContextNode.GetAsText();
    105    MOZ_ASSERT(textNode);
    106 
    107    uint32_t textLength = textNode->Length();
    108    if (textLength == 0) {
    109      aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
    110      return nullptr;
    111    }
    112 
    113    // XXX Need to get logical XPath text node for CDATASection
    114    //     and Text nodes.
    115  } else if (nodeType != nsINode::DOCUMENT_NODE &&
    116             nodeType != nsINode::ELEMENT_NODE &&
    117             nodeType != nsINode::ATTRIBUTE_NODE &&
    118             nodeType != nsINode::COMMENT_NODE &&
    119             nodeType != nsINode::PROCESSING_INSTRUCTION_NODE) {
    120    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
    121    return nullptr;
    122  }
    123 
    124  Maybe<txXPathNode> contextNode =
    125      txXPathNativeNode::createXPathNode(&aContextNode);
    126  if (!contextNode) {
    127    aRv.Throw(NS_ERROR_FAILURE);
    128    return nullptr;
    129  }
    130 
    131  EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
    132                           mRecycler);
    133  RefPtr<txAExprResult> exprResult;
    134  aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
    135  if (aRv.Failed()) {
    136    return nullptr;
    137  }
    138 
    139  uint16_t resultType = aType;
    140  if (aType == XPathResult::ANY_TYPE) {
    141    short exprResultType = exprResult->getResultType();
    142    switch (exprResultType) {
    143      case txAExprResult::NUMBER:
    144        resultType = XPathResult::NUMBER_TYPE;
    145        break;
    146      case txAExprResult::STRING:
    147        resultType = XPathResult::STRING_TYPE;
    148        break;
    149      case txAExprResult::BOOLEAN:
    150        resultType = XPathResult::BOOLEAN_TYPE;
    151        break;
    152      case txAExprResult::NODESET:
    153        resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
    154        break;
    155      case txAExprResult::RESULT_TREE_FRAGMENT:
    156        aRv.Throw(NS_ERROR_FAILURE);
    157        return nullptr;
    158    }
    159  }
    160 
    161  RefPtr<XPathResult> xpathResult = aInResult;
    162  if (!xpathResult) {
    163    xpathResult = new XPathResult(&aContextNode);
    164  }
    165 
    166  xpathResult->SetExprResult(exprResult, resultType, &aContextNode, aRv);
    167  if (aRv.Failed()) {
    168    return nullptr;
    169  }
    170 
    171  return xpathResult.forget();
    172 }
    173 
    174 /*
    175 * Implementation of the txIEvalContext private to XPathExpression
    176 * EvalContextImpl bases on only one context node and no variables
    177 */
    178 
    179 nsresult EvalContextImpl::getVariable(int32_t aNamespace, nsAtom* aLName,
    180                                      txAExprResult*& aResult) {
    181  aResult = 0;
    182  return NS_ERROR_INVALID_ARG;
    183 }
    184 
    185 nsresult EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode,
    186                                              bool& aAllowed) {
    187  aAllowed = false;
    188 
    189  return NS_OK;
    190 }
    191 
    192 void* EvalContextImpl::getPrivateContext() {
    193  // we don't have a private context here.
    194  return nullptr;
    195 }
    196 
    197 txResultRecycler* EvalContextImpl::recycler() { return mRecycler; }
    198 
    199 void EvalContextImpl::receiveError(const nsAString& aMsg, nsresult aRes) {
    200  mLastError = aRes;
    201  // forward aMsg to console service?
    202 }
    203 
    204 const txXPathNode& EvalContextImpl::getContextNode() { return mContextNode; }
    205 
    206 uint32_t EvalContextImpl::size() { return mContextSize; }
    207 
    208 uint32_t EvalContextImpl::position() { return mContextPosition; }
    209 
    210 }  // namespace mozilla::dom