DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (1aeaa33a64f9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

#ifndef mozilla_dom_DocumentOrShadowRoot_h__
#define mozilla_dom_DocumentOrShadowRoot_h__

#include "nsTArray.h"
#include "nsIdentifierMapEntry.h"

class nsContentList;
class nsINode;

namespace mozilla {
class StyleSheet;

namespace dom {

class StyleSheetList;
class ShadowRoot;

/**
 * A class meant to be shared by ShadowRoot and Document, that holds a list of
 * stylesheets.
 *
 * TODO(emilio, bug 1418159): In the future this should hold most of the
 * relevant style state, this should allow us to fix bug 548397.
 */
class DocumentOrShadowRoot {
  enum class Kind {
    Document,
    ShadowRoot,
  };

 public:
  explicit DocumentOrShadowRoot(nsIDocument&);
  explicit DocumentOrShadowRoot(mozilla::dom::ShadowRoot&);

  nsINode& AsNode() { return mAsNode; }

  const nsINode& AsNode() const { return mAsNode; }

  StyleSheet* SheetAt(size_t aIndex) const {
    return mStyleSheets.SafeElementAt(aIndex);
  }

  size_t SheetCount() const { return mStyleSheets.Length(); }

  int32_t IndexOfSheet(const StyleSheet& aSheet) const {
    return mStyleSheets.IndexOf(&aSheet);
  }

  void InsertSheetAt(size_t aIndex, StyleSheet& aSheet) {
    mStyleSheets.InsertElementAt(aIndex, &aSheet);
  }

  void RemoveSheet(StyleSheet& aSheet) { mStyleSheets.RemoveElement(&aSheet); }

  void AppendStyleSheet(StyleSheet& aSheet) {
    mStyleSheets.AppendElement(&aSheet);
  }

  StyleSheetList& EnsureDOMStyleSheets();

  Element* GetElementById(const nsAString& aElementId);

  /**
   * This method returns _all_ the elements in this scope which have id
   * aElementId, if there are any.  Otherwise it returns null.
   *
   * This is useful for stuff like QuerySelector optimization and such.
   */
  inline const nsTArray<Element*>* GetAllElementsForId(
      const nsAString& aElementId) const;

  already_AddRefed<nsContentList> GetElementsByTagName(
      const nsAString& aTagName) {
    return NS_GetContentList(&AsNode(), kNameSpaceID_Unknown, aTagName);
  }

  already_AddRefed<nsContentList> GetElementsByTagNameNS(
      const nsAString& aNamespaceURI, const nsAString& aLocalName);

  already_AddRefed<nsContentList> GetElementsByTagNameNS(
      const nsAString& aNamespaceURI, const nsAString& aLocalName,
      mozilla::ErrorResult&);

  already_AddRefed<nsContentList> GetElementsByClassName(
      const nsAString& aClasses);

  ~DocumentOrShadowRoot() = default;

  Element* GetPointerLockElement();
  Element* GetFullscreenElement();

  Element* ElementFromPoint(float aX, float aY);
  void ElementsFromPoint(float aX, float aY,
                         nsTArray<RefPtr<mozilla::dom::Element>>& aElements);

  /**
   * Helper for nsIDOMDocument::elementFromPoint implementation that allows
   * ignoring the scroll frame and/or avoiding layout flushes.
   *
   * @see nsIDOMWindowUtils::elementFromPoint
   */
  Element* ElementFromPointHelper(float aX, float aY,
                                  bool aIgnoreRootScrollFrame,
                                  bool aFlushLayout);
  enum ElementsFromPointFlags {
    IGNORE_ROOT_SCROLL_FRAME = 1,
    FLUSH_LAYOUT = 2,
    IS_ELEMENT_FROM_POINT = 4
  };

  void ElementsFromPointHelper(
      float aX, float aY, uint32_t aFlags,
      nsTArray<RefPtr<mozilla::dom::Element>>& aElements);

 protected:
  nsIContent* Retarget(nsIContent* aContent) const;

  /**
   * If focused element's subtree root is this document or shadow root, return
   * focused element, otherwise, get the shadow host recursively until the
   * shadow host's subtree root is this document or shadow root.
   */
  Element* GetRetargetedFocusedElement();

  nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
  RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;

  /*
   * mIdentifierMap works as follows for IDs:
   * 1) Attribute changes affect the table immediately (removing and adding
   *    entries as needed).
   * 2) Removals from the DOM affect the table immediately
   * 3) Additions to the DOM always update existing entries for names, and add
   *    new ones for IDs.
   */
  nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;

  nsINode& mAsNode;
  const Kind mKind;
};

inline const nsTArray<Element*>* DocumentOrShadowRoot::GetAllElementsForId(
    const nsAString& aElementId) const {
  if (aElementId.IsEmpty()) {
    return nullptr;
  }

  nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aElementId);
  return entry ? &entry->GetIdElements() : nullptr;
}

}  // namespace dom

}  // namespace mozilla

#endif