/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"

#include <algorithm>
#include "base/debug/dump_without_crashing.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h"
#include "third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/composition_marker.h"
#include "third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/custom_highlight_marker.h"
#include "third_party/blink/renderer/core/editing/markers/custom_highlight_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/grammar_marker.h"
#include "third_party/blink/renderer/core/editing/markers/grammar_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h"
#include "third_party/blink/renderer/core/editing/markers/spelling_marker.h"
#include "third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker.h"
#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/highlight/highlight_style_utils.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"

namespace blink {

namespace {

DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(
    DocumentMarker::MarkerType type) {
  switch (type) {
    case DocumentMarker::kSpelling:
      return DocumentMarker::kSpellingMarkerIndex;
    case DocumentMarker::kGrammar:
      return DocumentMarker::kGrammarMarkerIndex;
    case DocumentMarker::kTextMatch:
      return DocumentMarker::kTextMatchMarkerIndex;
    case DocumentMarker::kComposition:
      return DocumentMarker::kCompositionMarkerIndex;
    case DocumentMarker::kActiveSuggestion:
      return DocumentMarker::kActiveSuggestionMarkerIndex;
    case DocumentMarker::kSuggestion:
      return DocumentMarker::kSuggestionMarkerIndex;
    case DocumentMarker::kTextFragment:
      return DocumentMarker::kTextFragmentMarkerIndex;
    case DocumentMarker::kCustomHighlight:
      return DocumentMarker::kCustomHighlightMarkerIndex;
  }

  NOTREACHED_IN_MIGRATION();
  return DocumentMarker::kSpellingMarkerIndex;
}

DocumentMarkerList* CreateListForType(DocumentMarker::MarkerType type) {
  switch (type) {
    case DocumentMarker::kActiveSuggestion:
      return MakeGarbageCollected<ActiveSuggestionMarkerListImpl>();
    case DocumentMarker::kComposition:
      return MakeGarbageCollected<CompositionMarkerListImpl>();
    case DocumentMarker::kSpelling:
      return MakeGarbageCollected<SpellingMarkerListImpl>();
    case DocumentMarker::kGrammar:
      return MakeGarbageCollected<GrammarMarkerListImpl>();
    case DocumentMarker::kSuggestion:
      return MakeGarbageCollected<SuggestionMarkerListImpl>();
    case DocumentMarker::kTextMatch:
      return MakeGarbageCollected<TextMatchMarkerListImpl>();
    case DocumentMarker::kTextFragment:
      return MakeGarbageCollected<TextFragmentMarkerListImpl>();
    case DocumentMarker::kCustomHighlight:
      return MakeGarbageCollected<CustomHighlightMarkerListImpl>();
  }

  NOTREACHED_IN_MIGRATION();
  return nullptr;
}

void InvalidateVisualOverflowForNode(const Node& node,
                                     DocumentMarker::MarkerType type) {
  if (!node.GetLayoutObject() ||
      !DocumentMarker::MarkerTypes::HighlightPseudos().Intersects(
          DocumentMarker::MarkerTypes(type))) {
    return;
  }
  if (HighlightStyleUtils::ShouldInvalidateVisualOverflow(node, type)) {
    node.GetLayoutObject()->InvalidateVisualOverflow();
  }
}

void InvalidatePaintForNode(const Node& node) {
  if (!node.GetLayoutObject()) {
    return;
  }

  node.GetLayoutObject()->SetShouldDoFullPaintInvalidation(
      PaintInvalidationReason::kDocumentMarker);

  // Tell accessibility about the new marker.
  AXObjectCache* ax_object_cache = node.GetDocument().ExistingAXObjectCache();
  if (!ax_object_cache) {
    return;
  }
  // TODO(nektar): Do major refactoring of all AX classes to comply with const
  // correctness.
  Node* non_const_node = &const_cast<Node&>(node);
  ax_object_cache->HandleTextMarkerDataAdded(non_const_node, non_const_node);
}

PositionInFlatTree SearchAroundPositionStart(
    const PositionInFlatTree& position) {
  const PositionInFlatTree start_of_word_or_null =
      StartOfWordPosition(position, kPreviousWordIfOnBoundary);
  return start_of_word_or_null.IsNotNull() ? start_of_word_or_null : position;
}

PositionInFlatTree SearchAroundPositionEnd(const PositionInFlatTree& position) {
  const PositionInFlatTree end_of_word_or_null =
      EndOfWordPosition(position, kNextWordIfOnBoundary);
  return end_of_word_or_null.IsNotNull() ? end_of_word_or_null : position;
}

}  // namespace

bool DocumentMarkerController::PossiblyHasMarkers(
    DocumentMarker::MarkerType type) const {
  return PossiblyHasMarkers(DocumentMarker::MarkerTypes(type));
}

inline bool DocumentMarkerController::PossiblyHasMarkers(
    DocumentMarker::MarkerTypes types) const {
  DCHECK(!markers_.empty() ||
         possibly_existing_marker_types_ == DocumentMarker::MarkerTypes(0));
  return possibly_existing_marker_types_.Intersects(types);
}

bool DocumentMarkerController::HasAnyMarkersForText(const Text& text) const {
  for (const auto& marker_map : markers_) {
    if (marker_map && marker_map->Contains(&text)) {
      return true;
    }
  }
  return false;
}

DocumentMarkerController::DocumentMarkerController(Document& document)
    : document_(&document) {
  markers_.Grow(DocumentMarker::kMarkerTypeIndexesCount);
}

void DocumentMarkerController::AddSpellingMarker(const EphemeralRange& range,
                                                 const String& description) {
  AddMarkerInternal(range, [&description](int start_offset, int end_offset) {
    return MakeGarbageCollected<SpellingMarker>(start_offset, end_offset,
                                                description);
  });
}

void DocumentMarkerController::AddGrammarMarker(const EphemeralRange& range,
                                                const String& description) {
  AddMarkerInternal(range, [&description](int start_offset, int end_offset) {
    return MakeGarbageCollected<GrammarMarker>(start_offset, end_offset,
                                               description);
  });
}

void DocumentMarkerController::AddTextMatchMarker(
    const EphemeralRange& range,
    TextMatchMarker::MatchStatus match_status) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(
      range,
      [match_status](int start_offset, int end_offset) {
        return MakeGarbageCollected<TextMatchMarker>(start_offset, end_offset,
                                                     match_status);
      },
      // Since we've already determined to have a match in the given range (via
      // FindBuffer), we can ignore the display lock for the purposes of finding
      // where to put the marker.
      TextIteratorBehavior::Builder().SetIgnoresDisplayLock(true).Build());
  // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a
  // throttling algorithm. crbug.com/6819.
}

void DocumentMarkerController::AddCompositionMarker(
    const EphemeralRange& range,
    Color underline_color,
    ui::mojom::ImeTextSpanThickness thickness,
    ui::mojom::ImeTextSpanUnderlineStyle underline_style,
    Color text_color,
    Color background_color) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(range,
                    [underline_color, thickness, underline_style, text_color,
                     background_color](int start_offset, int end_offset) {
                      return MakeGarbageCollected<CompositionMarker>(
                          start_offset, end_offset, underline_color, thickness,
                          underline_style, text_color, background_color);
                    });
}

void DocumentMarkerController::AddActiveSuggestionMarker(
    const EphemeralRange& range,
    Color underline_color,
    ui::mojom::ImeTextSpanThickness thickness,
    ui::mojom::ImeTextSpanUnderlineStyle underline_style,
    Color text_color,
    Color background_color) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(range,
                    [underline_color, thickness, underline_style, text_color,
                     background_color](int start_offset, int end_offset) {
                      return MakeGarbageCollected<ActiveSuggestionMarker>(
                          start_offset, end_offset, underline_color, thickness,
                          underline_style, text_color, background_color);
                    });
}

void DocumentMarkerController::AddSuggestionMarker(
    const EphemeralRange& range,
    const SuggestionMarkerProperties& properties) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(range, [&properties](int start_offset, int end_offset) {
    return MakeGarbageCollected<SuggestionMarker>(start_offset, end_offset,
                                                  properties);
  });
}

void DocumentMarkerController::AddTextFragmentMarker(
    const EphemeralRange& range) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(range, [](int start_offset, int end_offset) {
    return MakeGarbageCollected<TextFragmentMarker>(start_offset, end_offset);
  });
}

void DocumentMarkerController::AddCustomHighlightMarker(
    const EphemeralRange& range,
    const String& highlight_name,
    const Member<Highlight> highlight) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());
  AddMarkerInternal(
      range, [highlight_name, highlight](int start_offset, int end_offset) {
        return MakeGarbageCollected<CustomHighlightMarker>(
            start_offset, end_offset, highlight_name, highlight);
      });
}

void DocumentMarkerController::PrepareForDestruction() {
  for (auto& marker_map : markers_) {
    marker_map.Clear();
  }
  possibly_existing_marker_types_ = DocumentMarker::MarkerTypes();
  SetDocument(nullptr);
}

void DocumentMarkerController::RemoveMarkers(
    TextIterator& marked_text,
    DocumentMarker::MarkerTypes marker_types) {
  for (; !marked_text.AtEnd(); marked_text.Advance()) {
    if (!PossiblyHasMarkers(marker_types)) {
      return;
    }
    const Node& node = marked_text.CurrentContainer();
    auto* text_node = DynamicTo<Text>(node);
    if (!text_node) {
      continue;
    }
    int start_offset = marked_text.StartOffsetInCurrentContainer();
    int end_offset = marked_text.EndOffsetInCurrentContainer();
    for (DocumentMarker::MarkerType type : marker_types) {
      RemoveMarkersInternal(*text_node, start_offset, end_offset - start_offset,
                            type);
    }
  }
}

void DocumentMarkerController::RemoveMarkersInRange(
    const EphemeralRange& range,
    DocumentMarker::MarkerTypes marker_types) {
  DCHECK(!document_->NeedsLayoutTreeUpdate());

  TextIterator marked_text(range.StartPosition(), range.EndPosition());
  DocumentMarkerController::RemoveMarkers(marked_text, marker_types);
}

void DocumentMarkerController::AddMarkerInternal(
    const EphemeralRange& range,
    base::FunctionRef<DocumentMarker*(int, int)> create_marker_from_offsets,
    const TextIteratorBehavior& iterator_behavior) {
  DocumentMarkerGroup* new_marker_group =
      MakeGarbageCollected<DocumentMarkerGroup>();
  for (TextIterator marked_text(range.StartPosition(), range.EndPosition(),
                                iterator_behavior);
       !marked_text.AtEnd(); marked_text.Advance()) {
    const int start_offset_in_current_container =
        marked_text.StartOffsetInCurrentContainer();
    const int end_offset_in_current_container =
        marked_text.EndOffsetInCurrentContainer();

    DCHECK_GE(end_offset_in_current_container,
              start_offset_in_current_container);

    // TODO(editing-dev): TextIterator sometimes emits ranges where the start
    // and end offsets are the same. Investigate if TextIterator should be
    // changed to not do this. See crbug.com/727929
    if (end_offset_in_current_container == start_offset_in_current_container) {
      continue;
    }

    // Ignore text emitted by TextIterator for non-text nodes (e.g. implicit
    // newlines)
    const auto* text_node = DynamicTo<Text>(marked_text.CurrentContainer());
    if (!text_node) {
      continue;
    }

    DocumentMarker* const new_marker = create_marker_from_offsets(
        start_offset_in_current_container, end_offset_in_current_container);
    AddMarkerToNode(*text_node, new_marker);
    new_marker_group->Set(new_marker, text_node);
    marker_groups_.insert(new_marker, new_marker_group);
  }
}

void DocumentMarkerController::AddMarkerToNode(const Text& text,
                                               DocumentMarker* new_marker) {
  DCHECK_GE(text.length(), new_marker->EndOffset());
  possibly_existing_marker_types_ = possibly_existing_marker_types_.Add(
      DocumentMarker::MarkerTypes(new_marker->GetType()));
  SetDocument(document_);

  DocumentMarker::MarkerType new_marker_type = new_marker->GetType();
  const DocumentMarker::MarkerTypeIndex type_index =
      MarkerTypeToMarkerIndex(new_marker_type);
  Member<MarkerMap>& marker_map = markers_[type_index];
  if (!marker_map) {
    marker_map = MakeGarbageCollected<MarkerMap>();
    markers_[type_index] = marker_map;
  }

  MarkerList& markers = marker_map->insert(&text, nullptr).stored_value->value;
  if (!markers) {
    markers = CreateListForType(new_marker_type);
  }
  markers->Add(new_marker);

  InvalidatePaintForNode(text);
  InvalidateVisualOverflowForNode(text, new_marker->GetType());
}

// Moves markers from src_node to dst_node. Markers are moved if their start
// offset is less than length. Markers that run past that point are truncated.
void DocumentMarkerController::MoveMarkers(const Text& src_node,
                                           int length,
                                           const Text& dst_node) {
  if (length <= 0) {
    return;
  }

  if (!PossiblyHasMarkers(DocumentMarker::MarkerTypes::All())) {
    return;
  }

  bool doc_dirty = false;
  for (auto& marker_map : markers_) {
    if (!marker_map) {
      continue;
    }

    DocumentMarkerList* const src_markers = FindMarkers(marker_map, &src_node);
    if (!src_markers) {
      return;
    }
    DCHECK(!src_markers->IsEmpty());

    DocumentMarker::MarkerType type = src_markers->GetMarkers()[0]->GetType();
    auto& dst_marker_entry =
        marker_map->insert(&dst_node, nullptr).stored_value->value;
    if (!dst_marker_entry) {
      dst_marker_entry = CreateListForType(type);
    }
    DocumentMarkerList* const dst_markers = dst_marker_entry;
    DCHECK(src_markers != dst_markers);

    if (src_markers->MoveMarkers(length, dst_markers)) {
      doc_dirty = true;
      InvalidateVisualOverflowForNode(dst_node, type);
      for (const auto& marker : dst_markers->GetMarkers()) {
        auto it = marker_groups_.find(marker);
        if (it != marker_groups_.end())
          it->value->Set(marker, &dst_node);
      }
    }
    // MoveMarkers in a list can remove markers entirely when split across
    // the src and dst, in which case both lists may be empty despite
    // MoveMarkers returning false.
    if (src_markers->IsEmpty()) {
      InvalidateVisualOverflowForNode(src_node, type);
      marker_map->erase(&src_node);
      DidRemoveNodeFromMap(type);
    }
    if (dst_markers->IsEmpty()) {
      marker_map->erase(&dst_node);
      DidRemoveNodeFromMap(type);
    }
  }

  if (!doc_dirty) {
    return;
  }

  InvalidatePaintForNode(dst_node);
}

void DocumentMarkerController::DidRemoveNodeFromMap(
    DocumentMarker::MarkerType type,
    bool clear_document_allowed) {
  DocumentMarker::MarkerTypeIndex type_index = MarkerTypeToMarkerIndex(type);
  if (markers_[type_index]->empty()) {
    markers_[type_index] = nullptr;
    possibly_existing_marker_types_ = possibly_existing_marker_types_.Subtract(
        DocumentMarker::MarkerTypes(type));
  }
  if (clear_document_allowed &&
      possibly_existing_marker_types_ == DocumentMarker::MarkerTypes()) {
    SetDocument(nullptr);
  }
}

void DocumentMarkerController::RemoveMarkersInternal(
    const Text& text,
    unsigned start_offset,
    int length,
    DocumentMarker::MarkerType marker_type) {
  if (length <= 0) {
    return;
  }

  if (!PossiblyHasMarkers(DocumentMarker::MarkerTypes(marker_type))) {
    return;
  }

  MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(marker_type)];
  DCHECK(marker_map);

  DocumentMarkerList* const list = FindMarkers(marker_map, &text);
  if (!list) {
    return;
  }

  const unsigned end_offset = start_offset + length;
  for (const Member<DocumentMarker>& marker : list->GetMarkers()) {
    if (marker->EndOffset() > start_offset &&
        marker->StartOffset() < end_offset) {
      auto it = marker_groups_.find(marker);
      if (it != marker_groups_.end()) {
        it->value->Erase(marker);
        marker_groups_.erase(marker);
      }
    }
  }
  if (list->RemoveMarkers(start_offset, length)) {
    InvalidateVisualOverflowForNode(text, marker_type);
    InvalidatePaintForNode(text);
  }
  if (list->IsEmpty()) {
    marker_map->erase(&text);
    DidRemoveNodeFromMap(marker_type);
  }
}

DocumentMarkerList* DocumentMarkerController::FindMarkers(
    const MarkerMap* marker_map,
    const Text* key) const {
  auto it = marker_map->find(key);
  if (it != marker_map->end()) {
    DCHECK(it->value);
    return it->value.Get();
  }
  return nullptr;
}

DocumentMarkerList* DocumentMarkerController::FindMarkersForType(
    DocumentMarker::MarkerType type,
    const Text* key) const {
  const MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
  if (!marker_map) {
    return nullptr;
  }
  return FindMarkers(marker_map, key);
}

DocumentMarker* DocumentMarkerController::FirstMarkerAroundPosition(
    const PositionInFlatTree& position,
    DocumentMarker::MarkerTypes types) {
  if (position.IsNull())
    return nullptr;
  const PositionInFlatTree& start = SearchAroundPositionStart(position);
  const PositionInFlatTree& end = SearchAroundPositionEnd(position);

  if (start > end) {
    // TODO(crbug/1114021): Investigate why this might happen.
    DUMP_WILL_BE_NOTREACHED() << "|start| should be before |end|.";
    return nullptr;
  }

  const Node* const start_node = start.ComputeContainerNode();
  const unsigned start_offset = start.ComputeOffsetInContainerNode();
  const Node* const end_node = end.ComputeContainerNode();
  const unsigned end_offset = end.ComputeOffsetInContainerNode();

  for (const Node& node : EphemeralRangeInFlatTree(start, end).Nodes()) {
    auto* text_node = DynamicTo<Text>(node);
    if (!text_node) {
      continue;
    }

    const unsigned start_range_offset = node == start_node ? start_offset : 0;
    const unsigned end_range_offset =
        node == end_node ? end_offset : text_node->length();

    DocumentMarker* const found_marker = FirstMarkerIntersectingOffsetRange(
        *text_node, start_range_offset, end_range_offset, types);
    if (found_marker) {
      return found_marker;
    }
  }

  return nullptr;
}

DocumentMarker* DocumentMarkerController::FirstMarkerIntersectingEphemeralRange(
    const EphemeralRange& range,
    DocumentMarker::MarkerTypes types) {
  if (range.IsNull()) {
    return nullptr;
  }

  if (range.IsCollapsed()) {
    return FirstMarkerAroundPosition(
        ToPositionInFlatTree(range.StartPosition()), types);
  }

  const Node* const start_container =
      range.StartPosition().ComputeContainerNode();
  const Node* const end_container = range.EndPosition().ComputeContainerNode();

  auto* text_node = DynamicTo<Text>(start_container);
  if (!text_node) {
    return nullptr;
  }

  const unsigned start_offset =
      range.StartPosition().ComputeOffsetInContainerNode();
  const unsigned end_offset =
      start_container == end_container
          ? range.EndPosition().ComputeOffsetInContainerNode()
          : text_node->length();

  return FirstMarkerIntersectingOffsetRange(*text_node, start_offset,
                                            end_offset, types);
}

DocumentMarker* DocumentMarkerController::FirstMarkerIntersectingOffsetRange(
    const Text& node,
    unsigned start_offset,
    unsigned end_offset,
    DocumentMarker::MarkerTypes types) {
  if (!PossiblyHasMarkers(types)) {
    return nullptr;
  }

  // Minor optimization: if we have an empty range at a node boundary, it
  // doesn't fall in the interior of any marker.
  if (start_offset == 0 && end_offset == 0) {
    return nullptr;
  }
  const unsigned node_length = node.length();
  if (start_offset == node_length && end_offset == node_length) {
    return nullptr;
  }

  for (DocumentMarker::MarkerType type : types) {
    const DocumentMarkerList* const list = FindMarkersForType(type, &node);
    if (!list) {
      continue;
    }
    DocumentMarker* found_marker =
        list->FirstMarkerIntersectingRange(start_offset, end_offset);
    if (found_marker) {
      return found_marker;
    }
  }

  return nullptr;
}

DocumentMarkerGroup* DocumentMarkerController::FirstMarkerGroupAroundPosition(
    const PositionInFlatTree& position,
    DocumentMarker::MarkerTypes types) {
  return GetMarkerGroupForMarker(FirstMarkerAroundPosition(position, types));
}

DocumentMarkerGroup*
DocumentMarkerController::FirstMarkerGroupIntersectingEphemeralRange(
    const EphemeralRange& range,
    DocumentMarker::MarkerTypes types) {
  return GetMarkerGroupForMarker(
      FirstMarkerIntersectingEphemeralRange(range, types));
}

DocumentMarkerGroup* DocumentMarkerController::GetMarkerGroupForMarker(
    const DocumentMarker* marker) {
  if (marker) {
    auto it = marker_groups_.find(marker);
    if (it != marker_groups_.end()) {
      return it->value.Get();
    }
  }
  return nullptr;
}

HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
DocumentMarkerController::MarkersAroundPosition(
    const PositionInFlatTree& position,
    DocumentMarker::MarkerTypes types) {
  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
      node_marker_pairs;

  if (position.IsNull()) {
    return node_marker_pairs;
  }

  if (!PossiblyHasMarkers(types)) {
    return node_marker_pairs;
  }

  const PositionInFlatTree& start = SearchAroundPositionStart(position);
  const PositionInFlatTree& end = SearchAroundPositionEnd(position);

  if (start > end) {
    // TODO(crbug/1114021): Investigate why this might happen.
    base::debug::DumpWithoutCrashing();
    return node_marker_pairs;
  }

  const Node* const start_node = start.ComputeContainerNode();
  const unsigned start_offset = start.ComputeOffsetInContainerNode();
  const Node* const end_node = end.ComputeContainerNode();
  const unsigned end_offset = end.ComputeOffsetInContainerNode();

  for (const Node& node : EphemeralRangeInFlatTree(start, end).Nodes()) {
    auto* text_node = DynamicTo<Text>(node);
    if (!text_node) {
      continue;
    }

    const unsigned start_range_offset = node == start_node ? start_offset : 0;
    const unsigned end_range_offset =
        node == end_node ? end_offset : text_node->length();

    // Minor optimization: if we have an empty range at a node boundary, it
    // doesn't fall in the interior of any marker.
    if (start_range_offset == 0 && end_range_offset == 0)
      continue;
    const unsigned node_length = To<CharacterData>(node).length();
    if (start_range_offset == node_length && end_range_offset == node_length)
      continue;

    for (DocumentMarker::MarkerType type : types) {
      const DocumentMarkerList* const list =
          FindMarkersForType(type, text_node);
      if (!list) {
        continue;
      }

      const DocumentMarkerVector& marker_vector =
          list->MarkersIntersectingRange(start_range_offset, end_range_offset);

      for (DocumentMarker* marker : marker_vector)
        node_marker_pairs.push_back(std::make_pair(&To<Text>(node), marker));
    }
  }
  return node_marker_pairs;
}

HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
DocumentMarkerController::MarkersIntersectingRange(
    const EphemeralRangeInFlatTree& range,
    DocumentMarker::MarkerTypes types) {
  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
      node_marker_pairs;
  if (!PossiblyHasMarkers(types))
    return node_marker_pairs;

  const Node* const range_start_container =
      range.StartPosition().ComputeContainerNode();
  const unsigned range_start_offset =
      range.StartPosition().ComputeOffsetInContainerNode();
  const Node* const range_end_container =
      range.EndPosition().ComputeContainerNode();
  const unsigned range_end_offset =
      range.EndPosition().ComputeOffsetInContainerNode();

  for (Node& node : range.Nodes()) {
    auto* text_node = DynamicTo<Text>(node);
    if (!text_node)
      continue;

    const unsigned start_offset =
        node == range_start_container ? range_start_offset : 0;
    const unsigned max_character_offset = To<CharacterData>(node).length();
    const unsigned end_offset =
        node == range_end_container ? range_end_offset : max_character_offset;

    // Minor optimization: if we have an empty offset range at the boundary
    // of a text node, it doesn't fall into the interior of any marker.
    if (start_offset == 0 && end_offset == 0) {
      continue;
    }
    if (start_offset == max_character_offset && end_offset == 0) {
      continue;
    }

    for (DocumentMarker::MarkerType type : types) {
      const DocumentMarkerList* const list =
          FindMarkersForType(type, text_node);
      if (!list) {
        continue;
      }

      const DocumentMarkerVector& markers_from_this_list =
          list->MarkersIntersectingRange(start_offset, end_offset);
      for (DocumentMarker* marker : markers_from_this_list)
        node_marker_pairs.push_back(std::make_pair(&To<Text>(node), marker));
    }
  }

  return node_marker_pairs;
}

DocumentMarkerVector DocumentMarkerController::MarkersFor(
    const Text& text,
    DocumentMarker::MarkerTypes marker_types) const {
  DocumentMarkerVector result;
  if (!PossiblyHasMarkers(marker_types))
    return result;

  // If requesting a single marker type, make use of the fact
  // that markers are already sorted.
  std::optional<DocumentMarker::MarkerType> lone_marker =
      marker_types.IsOneMarkerType();
  if (lone_marker) {
    DocumentMarkerList* const list = FindMarkersForType(*lone_marker, &text);
    return list ? list->GetMarkers() : result;
  }

  for (DocumentMarker::MarkerType type : marker_types) {
    DocumentMarkerList* const list = FindMarkersForType(type, &text);
    if (!list) {
      continue;
    }

    result.AppendVector(list->GetMarkers());
  }

  std::sort(result.begin(), result.end(),
            [](const Member<DocumentMarker>& marker1,
               const Member<DocumentMarker>& marker2) {
              return marker1->StartOffset() < marker2->StartOffset();
            });
  return result;
}

DocumentMarkerVector DocumentMarkerController::MarkersFor(
    const Text& text,
    DocumentMarker::MarkerType marker_type,
    unsigned start_offset,
    unsigned end_offset) const {
  DocumentMarkerVector result;
  DocumentMarkerList* const list = FindMarkersForType(marker_type, &text);
  return list ? list->MarkersIntersectingRange(start_offset, end_offset)
              : result;
}

DocumentMarkerVector DocumentMarkerController::Markers() const {
  DocumentMarkerVector result;
  for (auto& marker_map : markers_) {
    if (!marker_map) {
      continue;
    }
    for (const auto& node_markers : *marker_map) {
      DocumentMarkerList* list = node_markers.value;
      result.AppendVector(list->GetMarkers());
    }
  }
  std::sort(result.begin(), result.end(),
            [](const Member<DocumentMarker>& marker1,
               const Member<DocumentMarker>& marker2) {
              return marker1->StartOffset() < marker2->StartOffset();
            });
  return result;
}

void DocumentMarkerController::ApplyToMarkersOfType(
    base::FunctionRef<void(const Text&, DocumentMarker*)> func,
    DocumentMarker::MarkerType type) {
  if (!PossiblyHasMarkers(type)) {
    return;
  }
  MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
  DCHECK(marker_map);
  for (auto& node_markers : *marker_map) {
    DocumentMarkerList* list = node_markers.value;
    const HeapVector<Member<DocumentMarker>>& markers = list->GetMarkers();
    for (auto& marker : markers) {
      func(*node_markers.key, marker);
    }
  }
}

void DocumentMarkerController::MergeOverlappingMarkers(
    DocumentMarker::MarkerType type) {
  MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
  if (!marker_map) {
    return;
  }
  for (auto& node_markers : *marker_map) {
    DCHECK(node_markers.value);
    node_markers.value->MergeOverlappingMarkers();
  }
}

DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
    const Text& text) const {
  DocumentMarker::MarkerTypes excluded_highlight_pseudos =
      DocumentMarker::MarkerTypes::HighlightPseudos();
  DocumentMarkerVector markers_to_paint{};

  // We don't render composition or spelling markers that overlap suggestion
  // markers.
  // Note: DocumentMarkerController::MarkersFor() returns markers sorted by
  // start offset.
  const DocumentMarkerVector& suggestion_markers =
      MarkersFor(text, DocumentMarker::MarkerTypes::Suggestion());
  if (suggestion_markers.empty()) {
    // If there are no suggestion markers, we can return early as a minor
    // performance optimization.
    markers_to_paint.AppendVector(MarkersFor(
        text, DocumentMarker::MarkerTypes::AllBut(
                  DocumentMarker::MarkerTypes(DocumentMarker::kSuggestion |
                                              DocumentMarker::kCustomHighlight))
                  .Subtract(excluded_highlight_pseudos)));
    return markers_to_paint;
  }

  const DocumentMarkerVector& markers_overridden_by_suggestion_markers =
      MarkersFor(text,
                 DocumentMarker::MarkerTypes(DocumentMarker::kComposition |
                                             DocumentMarker::kSpelling)
                     .Subtract(excluded_highlight_pseudos));

  Vector<unsigned> suggestion_starts;
  Vector<unsigned> suggestion_ends;
  for (const DocumentMarker* suggestion_marker : suggestion_markers) {
    suggestion_starts.push_back(suggestion_marker->StartOffset());
    suggestion_ends.push_back(suggestion_marker->EndOffset());
  }

  // StartOffsets are already sorted.
  std::sort(suggestion_ends.begin(), suggestion_ends.end());

  unsigned suggestion_starts_index = 0;
  unsigned suggestion_ends_index = 0;
  unsigned number_suggestions_currently_inside = 0;

  for (DocumentMarker* marker : markers_overridden_by_suggestion_markers) {
    while (suggestion_starts_index < suggestion_starts.size() &&
           suggestion_starts[suggestion_starts_index] <=
               marker->StartOffset()) {
      ++suggestion_starts_index;
      ++number_suggestions_currently_inside;
    }
    while (suggestion_ends_index < suggestion_ends.size() &&
           suggestion_ends[suggestion_ends_index] <= marker->StartOffset()) {
      ++suggestion_ends_index;
      --number_suggestions_currently_inside;
    }

    // At this point, number_suggestions_currently_inside should be equal to the
    // number of suggestion markers overlapping the point marker->StartOffset()
    // (marker endpoints don't count as overlapping).

    // Marker is overlapped by a suggestion marker, do not paint.
    if (number_suggestions_currently_inside) {
      continue;
    }

    // Verify that no suggestion marker starts before the current marker ends.
    if (suggestion_starts_index < suggestion_starts.size() &&
        suggestion_starts[suggestion_starts_index] < marker->EndOffset()) {
      continue;
    }

    markers_to_paint.push_back(marker);
  }

  markers_to_paint.AppendVector(suggestion_markers);

  markers_to_paint.AppendVector(MarkersFor(
      text,
      DocumentMarker::MarkerTypes::AllBut(
          DocumentMarker::MarkerTypes(
              DocumentMarker::kComposition | DocumentMarker::kSpelling |
              DocumentMarker::kSuggestion | DocumentMarker::kCustomHighlight))
          .Subtract(excluded_highlight_pseudos)));

  return markers_to_paint;
}

bool DocumentMarkerController::PossiblyHasTextMatchMarkers() const {
  return PossiblyHasMarkers(DocumentMarker::kTextMatch);
}

Vector<gfx::Rect> DocumentMarkerController::LayoutRectsForTextMatchMarkers() {
  DCHECK(!document_->View()->NeedsLayout());
  DCHECK(!document_->NeedsLayoutTreeUpdate());

  Vector<gfx::Rect> result;

  if (!PossiblyHasMarkers(DocumentMarker::kTextMatch)) {
    return result;
  }

  MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kTextMatch)];
  DCHECK(marker_map);
  MarkerMap::iterator end = marker_map->end();
  for (MarkerMap::iterator node_iterator = marker_map->begin();
       node_iterator != end; ++node_iterator) {
    // inner loop; process each marker in this node
    const Node& node = *node_iterator->key;
    if (!node.isConnected()) {
      continue;
    }
    DocumentMarkerList* const list = node_iterator->value.Get();
    if (!list) {
      continue;
    }
    result.AppendVector(To<TextMatchMarkerListImpl>(list)->LayoutRects(node));
  }

  return result;
}

static void InvalidatePaintForTickmarks(const Node& node) {
  if (LayoutView* layout_view = node.GetDocument().GetLayoutView())
    layout_view->InvalidatePaintForTickmarks();
}

void DocumentMarkerController::InvalidateRectsForTextMatchMarkersInNode(
    const Text& node) {
  if (!PossiblyHasMarkers(DocumentMarker::kTextMatch)) {
    return;
  }

  const DocumentMarkerList* const marker_list =
      FindMarkersForType(DocumentMarker::kTextMatch, &node);
  if (!marker_list) {
    return;
  }

  const HeapVector<Member<DocumentMarker>>& markers_in_list =
      marker_list->GetMarkers();
  for (auto& marker : markers_in_list)
    To<TextMatchMarker>(marker.Get())->Invalidate();

  InvalidatePaintForTickmarks(node);
}

void DocumentMarkerController::InvalidateRectsForAllTextMatchMarkers() {
  if (!PossiblyHasMarkers(DocumentMarker::kTextMatch)) {
    return;
  }

  const MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kTextMatch)];
  DCHECK(marker_map);

  for (auto& node_markers : *marker_map) {
    const Text& node = *node_markers.key;
    InvalidateRectsForTextMatchMarkersInNode(node);
  }
}

void DocumentMarkerController::Trace(Visitor* visitor) const {
  visitor->Trace(markers_);
  visitor->Trace(marker_groups_);
  visitor->Trace(document_);
  SynchronousMutationObserver::Trace(visitor);
}

void DocumentMarkerController::RemoveMarkersForNode(
    const Text& text,
    DocumentMarker::MarkerTypes marker_types) {
  if (!PossiblyHasMarkers(marker_types)) {
    return;
  }

  for (auto type : marker_types) {
    MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
    if (!marker_map) {
      continue;
    }
    MarkerMap::iterator iterator = marker_map->find(&text);
    if (iterator != marker_map->end()) {
      RemoveMarkersFromList(iterator, type);
    }
  }
}

void DocumentMarkerController::RemoveSpellingMarkersUnderWords(
    const Vector<String>& words) {
  for (DocumentMarker::MarkerType type :
       DocumentMarker::MarkerTypes::Misspelling()) {
    MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
    if (!marker_map) {
      continue;
    }
    HeapHashSet<WeakMember<Text>> nodes_to_remove;
    for (auto& node_markers : *marker_map) {
      const Text& text = *node_markers.key;
      DocumentMarkerList* const list = node_markers.value;
      if (To<SpellCheckMarkerListImpl>(list)->RemoveMarkersUnderWords(
              text.data(), words)) {
        InvalidateVisualOverflowForNode(text, type);
        InvalidatePaintForNode(text);
        if (list->IsEmpty()) {
          nodes_to_remove.insert(node_markers.key);
        }
      }
    }
    if (nodes_to_remove.size()) {
      for (auto node : nodes_to_remove) {
        marker_map->erase(node);
      }
      nodes_to_remove.clear();
      DidRemoveNodeFromMap(type);
    }
  }
}

void DocumentMarkerController::RemoveSuggestionMarkerInRangeOnFinish(
    const EphemeralRangeInFlatTree& range) {
  // MarkersIntersectingRange() might be expensive. In practice, we hope we will
  // only check one node for composing range.
  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
      node_marker_pairs = MarkersIntersectingRange(
          range, DocumentMarker::MarkerTypes::Suggestion());
  MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kSuggestion)];
  for (const auto& node_marker_pair : node_marker_pairs) {
    auto* suggestion_marker =
        To<SuggestionMarker>(node_marker_pair.second.Get());
    if (suggestion_marker->NeedsRemovalOnFinishComposing()) {
      const Text& text = *node_marker_pair.first;
      DocumentMarkerList* const list = FindMarkers(marker_map, &text);
      // RemoveMarkerByTag() might be expensive. In practice, we have at most
      // one suggestion marker needs to be removed.
      To<SuggestionMarkerListImpl>(list)->RemoveMarkerByTag(
          suggestion_marker->Tag());
      InvalidatePaintForNode(text);
      if (list->IsEmpty()) {
        marker_map->erase(&text);
        DidRemoveNodeFromMap(DocumentMarker::kSuggestion);
      }
    }
  }
}

void DocumentMarkerController::RemoveSuggestionMarkerByType(
    const EphemeralRangeInFlatTree& range,
    const SuggestionMarker::SuggestionType& type) {
  // MarkersIntersectingRange() might be expensive. In practice, we hope we will
  // only check one node for the range.
  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
      node_marker_pairs = MarkersIntersectingRange(
          range, DocumentMarker::MarkerTypes::Suggestion());
  MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kSuggestion)];
  for (const auto& node_marker_pair : node_marker_pairs) {
    const Text& text = *node_marker_pair.first;
    DocumentMarkerList* const list = FindMarkers(marker_map, &text);
    // RemoveMarkerByType() might be expensive. In practice, we have at most
    // one suggestion marker needs to be removed.
    To<SuggestionMarkerListImpl>(list)->RemoveMarkerByType(type);
    InvalidatePaintForNode(text);
    if (list->IsEmpty()) {
      marker_map->erase(node_marker_pair.first);
      DidRemoveNodeFromMap(DocumentMarker::kSuggestion);
    }
  }
}

void DocumentMarkerController::RemoveSuggestionMarkerByType(
    const SuggestionMarker::SuggestionType& type) {
  if (!PossiblyHasMarkers(DocumentMarker::kSuggestion)) {
    return;
  }
  MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kSuggestion)];
  DCHECK(marker_map);
  for (const auto& node_markers : *marker_map) {
    DocumentMarkerList* const list = node_markers.value;
    if (To<SuggestionMarkerListImpl>(list)->RemoveMarkerByType(type)) {
      InvalidatePaintForNode(*node_markers.key);
      if (list->IsEmpty()) {
        marker_map->erase(node_markers.key);
        DidRemoveNodeFromMap(DocumentMarker::kSuggestion);
      }
      return;
    }
  }
}

void DocumentMarkerController::RemoveSuggestionMarkerByTag(const Text& text,
                                                           int32_t marker_tag) {
  if (!PossiblyHasMarkers(DocumentMarker::kSuggestion)) {
    return;
  }
  MarkerMap* marker_map =
      markers_[MarkerTypeToMarkerIndex(DocumentMarker::kSuggestion)];
  DCHECK(marker_map);

  DocumentMarkerList* markers = marker_map->at(&text);
  auto* const list = To<SuggestionMarkerListImpl>(markers);
  if (!list->RemoveMarkerByTag(marker_tag)) {
    return;
  }
  if (list->IsEmpty()) {
    marker_map->erase(&text);
    DidRemoveNodeFromMap(DocumentMarker::kSuggestion);
  }
  InvalidatePaintForNode(text);
}

void DocumentMarkerController::RemoveMarkersOfTypes(
    DocumentMarker::MarkerTypes marker_types) {
  if (!PossiblyHasMarkers(marker_types)) {
    return;
  }

  HeapVector<Member<const Text>> nodes_with_markers;
  for (DocumentMarker::MarkerType type : marker_types) {
    MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
    if (!marker_map) {
      continue;
    }
    CopyKeysToVector(*marker_map, nodes_with_markers);
    for (const auto& node : nodes_with_markers) {
      MarkerMap::iterator iterator = marker_map->find(node);
      if (iterator != marker_map->end()) {
        RemoveMarkersFromList(iterator, type);
      }
    }
  }
}

void DocumentMarkerController::RemoveMarkersFromList(
    MarkerMap::iterator iterator,
    DocumentMarker::MarkerType marker_type) {
  DocumentMarkerList* const list = iterator->value.Get();
  list->Clear();

  const Text& node = *iterator->key;
  InvalidateVisualOverflowForNode(node, marker_type);
  InvalidatePaintForNode(node);
  InvalidatePaintForTickmarks(node);

  MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(marker_type)];
  marker_map->erase(iterator);
  DidRemoveNodeFromMap(marker_type);
}

void DocumentMarkerController::RepaintMarkers(
    DocumentMarker::MarkerTypes marker_types) {
  if (!PossiblyHasMarkers(marker_types)) {
    return;
  }
  DCHECK(!markers_.empty());

  for (auto type : marker_types) {
    const MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
    if (!marker_map) {
      continue;
    }
    for (auto& iterator : *marker_map) {
      InvalidatePaintForNode(*iterator.key);
    }
  }
}

bool DocumentMarkerController::SetTextMatchMarkersActive(
    const EphemeralRange& range,
    bool active) {
  if (!PossiblyHasMarkers(DocumentMarker::kTextMatch)) {
    return false;
  }

  DCHECK(!markers_.empty());

  const Node* const start_container =
      range.StartPosition().ComputeContainerNode();
  DCHECK(start_container);
  const Node* const end_container = range.EndPosition().ComputeContainerNode();
  DCHECK(end_container);

  const unsigned container_start_offset =
      range.StartPosition().ComputeOffsetInContainerNode();
  const unsigned container_end_offset =
      range.EndPosition().ComputeOffsetInContainerNode();

  bool marker_found = false;
  for (Node& node : range.Nodes()) {
    auto* text_node = DynamicTo<Text>(node);
    if (!text_node) {
      continue;
    }
    int start_offset = node == start_container ? container_start_offset : 0;
    int end_offset = node == end_container ? container_end_offset : INT_MAX;
    marker_found |=
        SetTextMatchMarkersActive(*text_node, start_offset, end_offset, active);
  }
  return marker_found;
}

bool DocumentMarkerController::SetTextMatchMarkersActive(const Text& text,
                                                         unsigned start_offset,
                                                         unsigned end_offset,
                                                         bool active) {
  DocumentMarkerList* const list =
      FindMarkersForType(DocumentMarker::kTextMatch, &text);
  if (!list) {
    return false;
  }

  bool doc_dirty = To<TextMatchMarkerListImpl>(list)->SetTextMatchMarkersActive(
      start_offset, end_offset, active);

  if (!doc_dirty) {
    return false;
  }
  InvalidatePaintForNode(text);
  return true;
}

#if DCHECK_IS_ON()
void DocumentMarkerController::ShowMarkers() const {
  StringBuilder builder;
  for (DocumentMarker::MarkerType type : DocumentMarker::MarkerTypes::All()) {
    const MarkerMap* marker_map = markers_[MarkerTypeToMarkerIndex(type)];
    if (!marker_map) {
      continue;
    }
    for (auto& node_iterator : *marker_map) {
      const Text* node = node_iterator.key;
      builder.AppendFormat("%p", node);
      DocumentMarkerList* const list = node_iterator.value;
      const HeapVector<Member<DocumentMarker>>& markers_in_list =
          list->GetMarkers();
      for (const DocumentMarker* marker : markers_in_list) {
        bool is_active_match = false;
        if (auto* text_match = DynamicTo<TextMatchMarker>(marker)) {
          is_active_match = text_match->IsActiveMatch();
        }

        builder.AppendFormat(
            " %u:[%u:%u](%d)", static_cast<uint32_t>(marker->GetType()),
            marker->StartOffset(), marker->EndOffset(), is_active_match);
      }
    }
    builder.Append("\n");
  }
  LOG(INFO) << builder.ToString().Utf8();
}
#endif

// SynchronousMutationObserver
void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node,
                                                      unsigned offset,
                                                      unsigned old_length,
                                                      unsigned new_length) {
  if (!PossiblyHasMarkers(DocumentMarker::MarkerTypes::All()))
    return;

  auto* text_node = DynamicTo<Text>(node);
  if (!text_node)
    return;

  bool did_shift_marker = false;
  for (auto& marker_map : markers_) {
    if (!marker_map) {
      continue;
    }
    DocumentMarkerList* const list = FindMarkers(marker_map, text_node);
    if (!list) {
      continue;
    }
    DCHECK(!list->IsEmpty());
    DocumentMarker::MarkerType type = list->GetMarkers()[0]->GetType();
    if (list->ShiftMarkers(node->data(), offset, old_length, new_length)) {
      did_shift_marker = true;
    }
    if (list->IsEmpty()) {
      InvalidateVisualOverflowForNode(*node, type);
      marker_map->erase(text_node);
      DidRemoveNodeFromMap(type, false);
    }
  }

  if (!did_shift_marker)
    return;
  if (!node->GetLayoutObject())
    return;
  InvalidateRectsForTextMatchMarkersInNode(*text_node);
  InvalidatePaintForNode(*node);
}

}  // namespace blink

#if DCHECK_IS_ON()
void ShowDocumentMarkers(const blink::DocumentMarkerController* controller) {
  if (controller)
    controller->ShowMarkers();
}
#endif
