tor-browser

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

RangeUtils.h (6501B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_RangeUtils_h
      8 #define mozilla_RangeUtils_h
      9 
     10 #include "mozilla/Maybe.h"
     11 #include "mozilla/RangeBoundary.h"
     12 #include "nsContentUtils.h"
     13 #include "nsIContent.h"
     14 #include "nsINode.h"
     15 
     16 namespace mozilla {
     17 
     18 namespace dom {
     19 class AbstractRange;
     20 
     21 /**
     22 * ShadowDOMSelectionHelpers contains the static methods to help extra values
     23 * based on whether or not the iterator allows to iterate nodes cross the shadow
     24 * boundary.
     25 */
     26 struct ShadowDOMSelectionHelpers {
     27  ShadowDOMSelectionHelpers() = delete;
     28 
     29  static nsINode* GetStartContainer(
     30      const AbstractRange* aRange,
     31      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     32 
     33  static uint32_t StartOffset(
     34      const AbstractRange* aRange,
     35      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     36 
     37  static nsINode* GetEndContainer(
     38      const AbstractRange* aRange,
     39      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     40 
     41  static uint32_t EndOffset(
     42      const AbstractRange* aRange,
     43      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     44 
     45  static nsINode* GetParentNodeInSameSelection(
     46      const nsINode& aNode,
     47      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     48 
     49  static ShadowRoot* GetShadowRoot(
     50      const nsINode* aNode,
     51      AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
     52 };
     53 }  // namespace dom
     54 
     55 class RangeUtils final {
     56  using AbstractRange = dom::AbstractRange;
     57 
     58 public:
     59  /**
     60   * GetRawRangeBoundaryBefore() and GetRawRangeBoundaryAfter() retrieve
     61   * RawRangeBoundary which points before or after aNode.
     62   */
     63  static const RawRangeBoundary GetRawRangeBoundaryAfter(nsINode* aNode) {
     64    MOZ_ASSERT(aNode);
     65 
     66    if (NS_WARN_IF(!aNode->IsContent())) {
     67      return RawRangeBoundary();
     68    }
     69 
     70    nsINode* parentNode = aNode->GetParentNode();
     71    if (!parentNode) {
     72      return RawRangeBoundary();
     73    }
     74    RawRangeBoundary afterNode(parentNode, aNode->AsContent());
     75    // If aNode isn't in the child nodes of its parent node, we hit this case.
     76    // This may occur when we're called by a mutation observer while aNode is
     77    // removed from the parent node.
     78    if (NS_WARN_IF(
     79            !afterNode.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets))) {
     80      return RawRangeBoundary();
     81    }
     82    return afterNode;
     83  }
     84 
     85  static const RawRangeBoundary GetRawRangeBoundaryBefore(nsINode* aNode) {
     86    MOZ_ASSERT(aNode);
     87 
     88    if (NS_WARN_IF(!aNode->IsContent())) {
     89      return RawRangeBoundary();
     90    }
     91 
     92    nsINode* parentNode = aNode->GetParentNode();
     93    if (!parentNode) {
     94      return RawRangeBoundary();
     95    }
     96    // If aNode isn't in the child nodes of its parent node, we hit this case.
     97    // This may occur when we're called by a mutation observer while aNode is
     98    // removed from the parent node.
     99    const Maybe<uint32_t> indexInParent = parentNode->ComputeIndexOf(aNode);
    100    if (MOZ_UNLIKELY(NS_WARN_IF(indexInParent.isNothing()))) {
    101      return RawRangeBoundary();
    102    }
    103    return RawRangeBoundary(parentNode, *indexInParent);
    104  }
    105 
    106  /**
    107   * Compute the root node of aNode for initializing range classes.
    108   * When aNode is in an anonymous subtree, this returns the shadow root or
    109   * binding parent.  Otherwise, the root node of the document or document
    110   * fragment.  If this returns nullptr, that means aNode can be neither the
    111   * start container nor end container of any range.
    112   */
    113  static nsINode* ComputeRootNode(nsINode* aNode);
    114 
    115  /**
    116   * XXX nsRange should accept 0 - UINT32_MAX as offset.  However, users of
    117   *     nsRange treat offset as int32_t.  Additionally, some other internal
    118   *     APIs like nsINode::ComputeIndexOf_Deprecated() use int32_t.  Therefore,
    119   *     nsRange should accept only 0 - INT32_MAX as valid offset for now.
    120   */
    121  static bool IsValidOffset(uint32_t aOffset) { return aOffset <= INT32_MAX; }
    122 
    123  /**
    124   * Return true if aStartContainer/aStartOffset and aEndContainer/aEndOffset
    125   * are valid start and end points for a range.  Otherwise, return false.
    126   */
    127  static bool IsValidPoints(nsINode* aStartContainer, uint32_t aStartOffset,
    128                            nsINode* aEndContainer, uint32_t aEndOffset) {
    129    return IsValidPoints(RawRangeBoundary(aStartContainer, aStartOffset),
    130                         RawRangeBoundary(aEndContainer, aEndOffset));
    131  }
    132  template <typename SPT, typename SRT, typename EPT, typename ERT>
    133  static bool IsValidPoints(const RangeBoundaryBase<SPT, SRT>& aStartBoundary,
    134                            const RangeBoundaryBase<EPT, ERT>& aEndBoundary);
    135 
    136  /**
    137   * The caller needs to ensure aNode is in the same doc like aAbstractRange.
    138   */
    139  template <TreeKind aKind = TreeKind::ShadowIncludingDOM,
    140            typename = std::enable_if_t<aKind == TreeKind::ShadowIncludingDOM ||
    141                                        aKind == TreeKind::Flat>>
    142  static Maybe<bool> IsNodeContainedInRange(
    143      const nsINode& aNode, const AbstractRange* aAbstractRange);
    144 
    145  /**
    146   * Utility routine to detect if a content node starts before a range and/or
    147   * ends after a range.  If neither it is contained inside the range.
    148   * Note that callers responsibility to ensure node in same doc as range.
    149   */
    150  template <TreeKind aKind = TreeKind::ShadowIncludingDOM,
    151            typename = std::enable_if_t<aKind == TreeKind::ShadowIncludingDOM ||
    152                                        aKind == TreeKind::Flat>>
    153  static nsresult CompareNodeToRange(const nsINode* aNode,
    154                                     const AbstractRange* aAbstractRange,
    155                                     bool* aNodeIsBeforeRange,
    156                                     bool* aNodeIsAfterRange);
    157 
    158  template <TreeKind aKind, typename SPT, typename SRT, typename EPT,
    159            typename ERT,
    160            typename = std::enable_if_t<aKind == TreeKind::ShadowIncludingDOM ||
    161                                        aKind == TreeKind::Flat>>
    162  static nsresult CompareNodeToRangeBoundaries(
    163      const nsINode* aNode, const RangeBoundaryBase<SPT, SRT>& aStartBoundary,
    164      const RangeBoundaryBase<EPT, ERT>& aEndBoundary, bool* aNodeIsBeforeRange,
    165      bool* aNodeIsAfterRange);
    166 };
    167 
    168 }  // namespace mozilla
    169 
    170 #endif  // #ifndef mozilla_RangeUtils_h