/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/finder/TextFinder.h"

#include "core/dom/AXObjectCacheBase.h"
#include "core/dom/Range.h"
#include "core/dom/ShadowRoot.h"
#include "core/editing/Editor.h"
#include "core/editing/EphemeralRange.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/SelectionTemplate.h"
#include "core/editing/VisibleSelection.h"
#include "core/editing/finder/FindInPageCoordinates.h"
#include "core/editing/finder/FindOptions.h"
#include "core/editing/iterators/SearchBuffer.h"
#include "core/editing/markers/DocumentMarker.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/exported/WebViewImpl.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/WebLocalFrameImpl.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/TextAutosizer.h"
#include "core/page/Page.h"
#include "platform/Timer.h"
#include "platform/wtf/Time.h"
#include "public/platform/TaskType.h"
#include "public/platform/WebFloatRect.h"
#include "public/platform/WebScrollIntoViewParams.h"
#include "public/platform/WebVector.h"
#include "public/web/WebFindOptions.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebViewClient.h"

namespace blink {

TextFinder::FindMatch::FindMatch(Range* range, int ordinal)
    : range_(range), ordinal_(ordinal) {}

void TextFinder::FindMatch::Trace(blink::Visitor* visitor) {
  visitor->Trace(range_);
}

class TextFinder::DeferredScopeStringMatches
    : public GarbageCollectedFinalized<TextFinder::DeferredScopeStringMatches> {
 public:
  static DeferredScopeStringMatches* Create(TextFinder* text_finder,
                                            int identifier,
                                            const WebString& search_text,
                                            const WebFindOptions& options) {
    return new DeferredScopeStringMatches(text_finder, identifier, search_text,
                                          options);
  }

  void Trace(blink::Visitor* visitor) { visitor->Trace(text_finder_); }

  void Dispose() { timer_.Stop(); }

 private:
  DeferredScopeStringMatches(TextFinder* text_finder,
                             int identifier,
                             const WebString& search_text,
                             const WebFindOptions& options)
      : timer_(text_finder->OwnerFrame().GetFrame()->GetTaskRunner(
                   TaskType::kUnspecedTimer),
               this,
               &DeferredScopeStringMatches::DoTimeout),
        text_finder_(text_finder),
        identifier_(identifier),
        search_text_(search_text),
        options_(options) {
    timer_.StartOneShot(TimeDelta(), FROM_HERE);
  }

  void DoTimeout(TimerBase*) {
    text_finder_->ResumeScopingStringMatches(identifier_, search_text_,
                                             options_);
  }

  TaskRunnerTimer<DeferredScopeStringMatches> timer_;
  Member<TextFinder> text_finder_;
  const int identifier_;
  const WebString search_text_;
  const WebFindOptions options_;
};

static void ScrollToVisible(Range* match) {
  const Node& first_node = *match->FirstNode();
  first_node.GetLayoutObject()->ScrollRectToVisible(
      LayoutRect(match->BoundingBox()),
      WebScrollIntoViewParams(ScrollAlignment::kAlignCenterIfNeeded,
                              ScrollAlignment::kAlignCenterIfNeeded,
                              kUserScroll));
  first_node.GetDocument().SetSequentialFocusNavigationStartingPoint(
      const_cast<Node*>(&first_node));
}

bool TextFinder::Find(int identifier,
                      const WebString& search_text,
                      const WebFindOptions& options,
                      bool wrap_within_frame,
                      bool* active_now) {
  if (!options.find_next)
    UnmarkAllTextMatches();
  else
    SetMarkerActive(active_match_.Get(), false);

  if (active_match_ &&
      &active_match_->OwnerDocument() != OwnerFrame().GetFrame()->GetDocument())
    active_match_ = nullptr;

  // If the user has selected something since the last Find operation we want
  // to start from there. Otherwise, we start searching from where the last Find
  // operation left off (either a Find or a FindNext operation).
  // TODO(editing-dev): The use of VisibleSelection should be audited. See
  // crbug.com/657237 for details.
  VisibleSelection selection(
      OwnerFrame().GetFrame()->Selection().ComputeVisibleSelectionInDOMTree());
  bool active_selection = !selection.IsNone();
  if (active_selection) {
    active_match_ = CreateRange(FirstEphemeralRangeOf(selection));
    OwnerFrame().GetFrame()->Selection().Clear();
  }

  DCHECK(OwnerFrame().GetFrame());
  DCHECK(OwnerFrame().GetFrame()->View());
  const FindOptions find_options =
      (options.forward ? 0 : kBackwards) |
      (options.match_case ? 0 : kCaseInsensitive) |
      (wrap_within_frame ? kWrapAround : 0) |
      (options.word_start ? kAtWordStarts : 0) |
      (options.medial_capital_as_word_start ? kTreatMedialCapitalAsWordStart
                                            : 0) |
      (options.find_next ? 0 : kStartInSelection);
  active_match_ = OwnerFrame().GetFrame()->GetEditor().FindRangeOfString(
      search_text, EphemeralRangeInFlatTree(active_match_.Get()), find_options);

  if (!active_match_) {
    // If we're finding next the next active match might not be in the current
    // frame.  In this case we don't want to clear the matches cache.
    if (!options.find_next)
      ClearFindMatchesCache();

    OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
    return false;
  }
  ScrollToVisible(active_match_);

  // If the user is browsing a page with autosizing, adjust the zoom to the
  // column where the next hit has been found. Doing this when autosizing is
  // not set will result in a zoom reset on small devices.
  if (OwnerFrame()
          .GetFrame()
          ->GetDocument()
          ->GetTextAutosizer()
          ->PageNeedsAutosizing()) {
    OwnerFrame().ViewImpl()->ZoomToFindInPageRect(
        OwnerFrame().GetFrameView()->ContentsToRootFrame(
            EnclosingIntRect(LayoutObject::AbsoluteBoundingBoxRectForRange(
                EphemeralRange(active_match_.Get())))));
  }

  bool was_active_frame = current_active_match_frame_;
  current_active_match_frame_ = true;

  bool is_active = SetMarkerActive(active_match_.Get(), true);
  if (active_now)
    *active_now = is_active;

  // Make sure no node is focused. See http://crbug.com/38700.
  OwnerFrame().GetFrame()->GetDocument()->ClearFocusedElement();

  // Set this frame as focused.
  OwnerFrame().ViewImpl()->SetFocusedFrame(&OwnerFrame());

  if (!options.find_next || active_selection || !is_active) {
    // This is either an initial Find operation, a Find-next from a new
    // start point due to a selection, or new matches were found during
    // Find-next due to DOM alteration (that couldn't be set as active), so
    // we set the flag to ask the scoping effort to find the active rect for
    // us and report it back to the UI.
    locating_active_rect_ = true;
  } else {
    if (!was_active_frame) {
      if (options.forward)
        active_match_index_ = 0;
      else
        active_match_index_ = last_match_count_ - 1;
    } else {
      if (options.forward)
        ++active_match_index_;
      else
        --active_match_index_;

      if (active_match_index_ + 1 > last_match_count_)
        active_match_index_ = 0;
      else if (active_match_index_ < 0)
        active_match_index_ = last_match_count_ - 1;
    }
    WebRect selection_rect = OwnerFrame().GetFrameView()->ContentsToRootFrame(
        active_match_->BoundingBox());
    ReportFindInPageSelection(selection_rect, active_match_index_ + 1,
                              identifier);
  }

  // We found something, so the result of the previous scoping may be outdated.
  last_find_request_completed_with_no_matches_ = false;

  return true;
}

void TextFinder::ClearActiveFindMatch() {
  current_active_match_frame_ = false;
  SetMarkerActive(active_match_.Get(), false);
  ResetActiveMatch();
}

LocalFrame* TextFinder::GetFrame() const {
  return OwnerFrame().GetFrame();
}

void TextFinder::SetFindEndstateFocusAndSelection() {
  if (!ActiveMatchFrame())
    return;

  Range* active_match = ActiveMatch();
  if (!active_match)
    return;

  // If the user has set the selection since the match was found, we
  // don't focus anything.
  if (!GetFrame()->Selection().GetSelectionInDOMTree().IsNone())
    return;

  // Need to clean out style and layout state before querying
  // Element::isFocusable().
  GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  // Try to find the first focusable node up the chain, which will, for
  // example, focus links if we have found text within the link.
  Node* node = active_match->FirstNode();
  if (node && node->IsInShadowTree()) {
    if (Node* host = node->OwnerShadowHost()) {
      if (IsHTMLInputElement(*host) || IsHTMLTextAreaElement(*host))
        node = host;
    }
  }
  const EphemeralRange active_match_range(active_match);
  if (node) {
    for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*node)) {
      if (!runner.IsElementNode())
        continue;
      Element& element = ToElement(runner);
      if (element.IsFocusable()) {
        // Found a focusable parent node. Set the active match as the
        // selection and focus to the focusable node.
        GetFrame()->Selection().SetSelectionAndEndTyping(
            SelectionInDOMTree::Builder()
                .SetBaseAndExtent(active_match_range)
                .Build());
        GetFrame()->GetDocument()->SetFocusedElement(
            &element, FocusParams(SelectionBehaviorOnFocus::kNone,
                                  kWebFocusTypeNone, nullptr));
        return;
      }
    }
  }

  // Iterate over all the nodes in the range until we find a focusable node.
  // This, for example, sets focus to the first link if you search for
  // text and text that is within one or more links.
  for (Node& runner : active_match_range.Nodes()) {
    if (!runner.IsElementNode())
      continue;
    Element& element = ToElement(runner);
    if (element.IsFocusable()) {
      GetFrame()->GetDocument()->SetFocusedElement(
          &element, FocusParams(SelectionBehaviorOnFocus::kNone,
                                kWebFocusTypeNone, nullptr));
      return;
    }
  }

  // No node related to the active match was focusable, so set the
  // active match as the selection (so that when you end the Find session,
  // you'll have the last thing you found highlighted) and make sure that
  // we have nothing focused (otherwise you might have text selected but
  // a link focused, which is weird).
  GetFrame()->Selection().SetSelectionAndEndTyping(
      SelectionInDOMTree::Builder()
          .SetBaseAndExtent(active_match_range)
          .Build());
  GetFrame()->GetDocument()->ClearFocusedElement();

  // Finally clear the active match, for two reasons:
  // We just finished the find 'session' and we don't want future (potentially
  // unrelated) find 'sessions' operations to start at the same place.
  // The WebLocalFrameImpl could get reused and the activeMatch could end up
  // pointing to a document that is no longer valid. Keeping an invalid
  // reference around is just asking for trouble.
  ResetActiveMatch();
}

void TextFinder::StopFindingAndClearSelection() {
  CancelPendingScopingEffort();

  // Remove all markers for matches found and turn off the highlighting.
  OwnerFrame().GetFrame()->GetDocument()->Markers().RemoveMarkersOfTypes(
      DocumentMarker::kTextMatch);
  OwnerFrame().GetFrame()->GetEditor().SetMarkedTextMatchesAreHighlighted(
      false);
  ClearFindMatchesCache();
  ResetActiveMatch();

  // Let the frame know that we don't want tickmarks anymore.
  OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
}

void TextFinder::ReportFindInPageResultToAccessibility(int identifier) {
  if (!active_match_)
    return;

  AXObjectCacheBase* ax_object_cache = ToAXObjectCacheBase(
      OwnerFrame().GetFrame()->GetDocument()->ExistingAXObjectCache());
  if (!ax_object_cache)
    return;

  Node* start_node = active_match_->startContainer();
  Node* end_node = active_match_->endContainer();
  ax_object_cache->HandleTextMarkerDataAdded(start_node, end_node);

  if (OwnerFrame().Client()) {
    OwnerFrame().Client()->HandleAccessibilityFindInPageResult(
        identifier, active_match_index_ + 1, blink::WebNode(start_node),
        active_match_->startOffset(), blink::WebNode(end_node),
        active_match_->endOffset());
  }
}

void TextFinder::StartScopingStringMatches(int identifier,
                                           const WebString& search_text,
                                           const WebFindOptions& options) {
  CancelPendingScopingEffort();

  // This is a brand new search, so we need to reset everything.
  // Scoping is just about to begin.
  scoping_in_progress_ = true;

  // Need to keep the current identifier locally in order to finish the
  // request in case the frame is detached during the process.
  find_request_identifier_ = identifier;

  // Clear highlighting for this frame.
  UnmarkAllTextMatches();

  // Clear the tickmarks and results cache.
  ClearFindMatchesCache();

  // Clear the total match count and increment markers version.
  ResetMatchCount();

  // Clear the counters from last operation.
  last_match_count_ = 0;
  next_invalidate_after_ = 0;

  // The view might be null on detached frames.
  LocalFrame* frame = OwnerFrame().GetFrame();
  if (frame && frame->GetPage())
    frame_scoping_ = true;

  // Now, defer scoping until later to allow find operation to finish quickly.
  ScopeStringMatchesSoon(identifier, search_text, options);
}

void TextFinder::ScopeStringMatches(int identifier,
                                    const WebString& search_text,
                                    const WebFindOptions& options) {
  if (!ShouldScopeMatches(search_text, options)) {
    FinishCurrentScopingEffort(identifier);
    return;
  }

  PositionInFlatTree search_start = PositionInFlatTree::FirstPositionInNode(
      *OwnerFrame().GetFrame()->GetDocument());
  PositionInFlatTree search_end = PositionInFlatTree::LastPositionInNode(
      *OwnerFrame().GetFrame()->GetDocument());
  DCHECK_EQ(search_start.GetDocument(), search_end.GetDocument());

  if (resume_scoping_from_range_) {
    // This is a continuation of a scoping operation that timed out and didn't
    // complete last time around, so we should start from where we left off.
    DCHECK(resume_scoping_from_range_->collapsed());
    search_start = FromPositionInDOMTree<EditingInFlatTreeStrategy>(
        resume_scoping_from_range_->EndPosition());
    if (search_start.GetDocument() != search_end.GetDocument())
      return;
  }

  // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  search_start.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  // This timeout controls how long we scope before releasing control. This
  // value does not prevent us from running for longer than this, but it is
  // periodically checked to see if we have exceeded our allocated time.
  const double kMaxScopingDuration = 0.1;  // seconds

  int match_count = 0;
  bool timed_out = false;
  double start_time = CurrentTime();
  PositionInFlatTree next_scoping_start;
  do {
    // Find next occurrence of the search string.
    // FIXME: (http://crbug.com/6818) This WebKit operation may run for longer
    // than the timeout value, and is not interruptible as it is currently
    // written. We may need to rewrite it with interruptibility in mind, or
    // find an alternative.
    const EphemeralRangeInFlatTree result =
        FindPlainText(EphemeralRangeInFlatTree(search_start, search_end),
                      search_text, options.match_case ? 0 : kCaseInsensitive);
    if (result.IsCollapsed()) {
      // Not found.
      break;
    }
    Range* result_range = Range::Create(
        result.GetDocument(), ToPositionInDOMTree(result.StartPosition()),
        ToPositionInDOMTree(result.EndPosition()));
    if (result_range->collapsed()) {
      // resultRange will be collapsed if the matched text spans over multiple
      // TreeScopes.  FIXME: Show such matches to users.
      search_start = result.EndPosition();
      continue;
    }

    ++match_count;

    // Catch a special case where Find found something but doesn't know what
    // the bounding box for it is. In this case we set the first match we find
    // as the active rect.
    IntRect result_bounds = result_range->BoundingBox();
    IntRect active_selection_rect;
    if (locating_active_rect_) {
      active_selection_rect =
          active_match_.Get() ? active_match_->BoundingBox() : result_bounds;
    }

    // If the Find function found a match it will have stored where the
    // match was found in m_activeSelectionRect on the current frame. If we
    // find this rect during scoping it means we have found the active
    // tickmark.
    bool found_active_match = false;
    if (locating_active_rect_ && (active_selection_rect == result_bounds)) {
      // We have found the active tickmark frame.
      current_active_match_frame_ = true;
      found_active_match = true;
      // We also know which tickmark is active now.
      active_match_index_ = total_match_count_ + match_count - 1;
      // To stop looking for the active tickmark, we set this flag.
      locating_active_rect_ = false;

      // Notify browser of new location for the selected rectangle.
      ReportFindInPageSelection(
          OwnerFrame().GetFrameView()->ContentsToRootFrame(result_bounds),
          active_match_index_ + 1, identifier);
    }

    OwnerFrame().GetFrame()->GetDocument()->Markers().AddTextMatchMarker(
        EphemeralRange(result_range),
        found_active_match ? TextMatchMarker::MatchStatus::kActive
                           : TextMatchMarker::MatchStatus::kInactive);

    find_matches_cache_.push_back(
        FindMatch(result_range, last_match_count_ + match_count));

    // Set the new start for the search range to be the end of the previous
    // result range. There is no need to use a VisiblePosition here,
    // since findPlainText will use a TextIterator to go over the visible
    // text nodes.
    search_start = result.EndPosition();

    next_scoping_start = search_start;
    timed_out = (CurrentTime() - start_time) >= kMaxScopingDuration;
  } while (!timed_out);

  if (next_scoping_start.IsNotNull()) {
    resume_scoping_from_range_ =
        Range::Create(*next_scoping_start.GetDocument(),
                      ToPositionInDOMTree(next_scoping_start),
                      ToPositionInDOMTree(next_scoping_start));
  }

  // Remember what we search for last time, so we can skip searching if more
  // letters are added to the search string (and last outcome was 0).
  last_search_string_ = search_text;

  if (match_count > 0) {
    OwnerFrame().GetFrame()->GetEditor().SetMarkedTextMatchesAreHighlighted(
        true);

    last_match_count_ += match_count;

    // Let the frame know how many matches we found during this pass.
    OwnerFrame().IncreaseMatchCount(match_count, identifier);
  }

  if (timed_out) {
    // If we found anything during this pass, we should redraw. However, we
    // don't want to spam too much if the page is extremely long, so if we
    // reach a certain point we start throttling the redraw requests.
    if (match_count > 0)
      InvalidateIfNecessary();

    // Scoping effort ran out of time, lets ask for another time-slice.
    ScopeStringMatchesSoon(identifier, search_text, options);
    return;  // Done for now, resume work later.
  }

  FinishCurrentScopingEffort(identifier);
}

void TextFinder::FlushCurrentScopingEffort(int identifier) {
  if (!OwnerFrame().GetFrame() || !OwnerFrame().GetFrame()->GetPage())
    return;

  frame_scoping_ = false;
  OwnerFrame().IncreaseMatchCount(0, identifier);
}

void TextFinder::FinishCurrentScopingEffort(int identifier) {
  if (!total_match_count_)
    OwnerFrame().GetFrame()->Selection().Clear();

  FlushCurrentScopingEffort(identifier);

  scoping_in_progress_ = false;
  last_find_request_completed_with_no_matches_ = !last_match_count_;

  // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
  OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
}

void TextFinder::CancelPendingScopingEffort() {
  if (deferred_scoping_work_) {
    deferred_scoping_work_->Dispose();
    deferred_scoping_work_.Clear();
  }

  active_match_index_ = -1;

  // Last request didn't complete.
  if (scoping_in_progress_)
    last_find_request_completed_with_no_matches_ = false;

  scoping_in_progress_ = false;

  resume_scoping_from_range_ = nullptr;
}

void TextFinder::IncreaseMatchCount(int identifier, int count) {
  if (count)
    ++find_match_markers_version_;

  total_match_count_ += count;

  // Update the UI with the latest findings.
  if (OwnerFrame().Client()) {
    OwnerFrame().Client()->ReportFindInPageMatchCount(
        identifier, total_match_count_, !frame_scoping_ || !total_match_count_);
  }
}

void TextFinder::ReportFindInPageSelection(const WebRect& selection_rect,
                                           int active_match_ordinal,
                                           int identifier) {
  // Update the UI with the latest selection rect.
  if (OwnerFrame().Client()) {
    OwnerFrame().Client()->ReportFindInPageSelection(
        identifier, active_match_ordinal, selection_rect);
  }
  // Update accessibility too, so if the user commits to this query
  // we can move accessibility focus to this result.
  ReportFindInPageResultToAccessibility(identifier);
}

void TextFinder::ResetMatchCount() {
  if (total_match_count_ > 0)
    ++find_match_markers_version_;

  total_match_count_ = 0;
  frame_scoping_ = false;
}

void TextFinder::ClearFindMatchesCache() {
  if (!find_matches_cache_.IsEmpty())
    ++find_match_markers_version_;

  find_matches_cache_.clear();
  find_match_rects_are_valid_ = false;
}

void TextFinder::UpdateFindMatchRects() {
  IntSize current_document_size = OwnerFrame().DocumentSize();
  if (document_size_for_current_find_match_rects_ != current_document_size) {
    document_size_for_current_find_match_rects_ = current_document_size;
    find_match_rects_are_valid_ = false;
  }

  size_t dead_matches = 0;
  for (FindMatch& match : find_matches_cache_) {
    if (!match.range_->BoundaryPointsValid() ||
        !match.range_->startContainer()->isConnected())
      match.rect_ = FloatRect();
    else if (!find_match_rects_are_valid_)
      match.rect_ = FindInPageRectFromRange(EphemeralRange(match.range_.Get()));

    if (match.rect_.IsEmpty())
      ++dead_matches;
  }

  // Remove any invalid matches from the cache.
  if (dead_matches) {
    HeapVector<FindMatch> filtered_matches;
    filtered_matches.ReserveCapacity(find_matches_cache_.size() - dead_matches);

    for (const FindMatch& match : find_matches_cache_) {
      if (!match.rect_.IsEmpty())
        filtered_matches.push_back(match);
    }

    find_matches_cache_.swap(filtered_matches);
  }

  // Invalidate the rects in child frames. Will be updated later during
  // traversal.
  if (!find_match_rects_are_valid_) {
    for (WebFrame* child = OwnerFrame().FirstChild(); child;
         child = child->NextSibling()) {
      ToWebLocalFrameImpl(child)
          ->EnsureTextFinder()
          .find_match_rects_are_valid_ = false;
    }
  }
  find_match_rects_are_valid_ = true;
}

WebFloatRect TextFinder::ActiveFindMatchRect() {
  if (!current_active_match_frame_ || !active_match_)
    return WebFloatRect();

  return WebFloatRect(FindInPageRectFromRange(EphemeralRange(ActiveMatch())));
}

void TextFinder::FindMatchRects(WebVector<WebFloatRect>& output_rects) {
  UpdateFindMatchRects();

  Vector<WebFloatRect> match_rects;
  match_rects.ReserveCapacity(match_rects.size() + find_matches_cache_.size());
  for (const FindMatch& match : find_matches_cache_) {
    DCHECK(!match.rect_.IsEmpty());
    match_rects.push_back(match.rect_);
  }

  output_rects = match_rects;
}

int TextFinder::SelectNearestFindMatch(const WebFloatPoint& point,
                                       WebRect* selection_rect) {
  int index = NearestFindMatch(point, nullptr);
  if (index != -1)
    return SelectFindMatch(static_cast<unsigned>(index), selection_rect);

  return -1;
}

int TextFinder::NearestFindMatch(const FloatPoint& point,
                                 float* distance_squared) {
  UpdateFindMatchRects();

  int nearest = -1;
  float nearest_distance_squared = FLT_MAX;
  for (size_t i = 0; i < find_matches_cache_.size(); ++i) {
    DCHECK(!find_matches_cache_[i].rect_.IsEmpty());
    FloatSize offset = point - find_matches_cache_[i].rect_.Center();
    float width = offset.Width();
    float height = offset.Height();
    float current_distance_squared = width * width + height * height;
    if (current_distance_squared < nearest_distance_squared) {
      nearest = i;
      nearest_distance_squared = current_distance_squared;
    }
  }

  if (distance_squared)
    *distance_squared = nearest_distance_squared;

  return nearest;
}

int TextFinder::SelectFindMatch(unsigned index, WebRect* selection_rect) {
  SECURITY_DCHECK(index < find_matches_cache_.size());

  Range* range = find_matches_cache_[index].range_;
  if (!range->BoundaryPointsValid() || !range->startContainer()->isConnected())
    return -1;

  // Check if the match is already selected.
  if (!current_active_match_frame_ || !active_match_ ||
      !AreRangesEqual(active_match_.Get(), range)) {
    active_match_index_ = find_matches_cache_[index].ordinal_ - 1;

    // Set this frame as the active frame (the one with the active highlight).
    current_active_match_frame_ = true;
    OwnerFrame().ViewImpl()->SetFocusedFrame(&OwnerFrame());

    if (active_match_)
      SetMarkerActive(active_match_.Get(), false);
    active_match_ = range;
    SetMarkerActive(active_match_.Get(), true);

    // Clear any user selection, to make sure Find Next continues on from the
    // match we just activated.
    OwnerFrame().GetFrame()->Selection().Clear();

    // Make sure no node is focused. See http://crbug.com/38700.
    OwnerFrame().GetFrame()->GetDocument()->ClearFocusedElement();
  }

  IntRect active_match_rect;
  IntRect active_match_bounding_box =
      EnclosingIntRect(LayoutObject::AbsoluteBoundingBoxRectForRange(
          EphemeralRange(active_match_.Get())));

  if (!active_match_bounding_box.IsEmpty()) {
    if (active_match_->FirstNode() &&
        active_match_->FirstNode()->GetLayoutObject()) {
      active_match_->FirstNode()->GetLayoutObject()->ScrollRectToVisible(
          LayoutRect(active_match_bounding_box),
          WebScrollIntoViewParams(ScrollAlignment::kAlignCenterIfNeeded,
                                  ScrollAlignment::kAlignCenterIfNeeded,
                                  kUserScroll));
    }

    // Zoom to the active match.
    active_match_rect = OwnerFrame().GetFrameView()->ContentsToRootFrame(
        active_match_bounding_box);
    OwnerFrame().ViewImpl()->ZoomToFindInPageRect(active_match_rect);
  }

  if (selection_rect)
    *selection_rect = active_match_rect;

  return active_match_index_ + 1;
}

TextFinder* TextFinder::Create(WebLocalFrameImpl& owner_frame) {
  return new TextFinder(owner_frame);
}

TextFinder::TextFinder(WebLocalFrameImpl& owner_frame)
    : owner_frame_(&owner_frame),
      current_active_match_frame_(false),
      active_match_index_(-1),
      resume_scoping_from_range_(nullptr),
      last_match_count_(-1),
      total_match_count_(-1),
      frame_scoping_(false),
      find_request_identifier_(-1),
      next_invalidate_after_(0),
      find_match_markers_version_(0),
      locating_active_rect_(false),
      scoping_in_progress_(false),
      last_find_request_completed_with_no_matches_(false),
      find_match_rects_are_valid_(false) {}

TextFinder::~TextFinder() = default;

bool TextFinder::SetMarkerActive(Range* range, bool active) {
  if (!range || range->collapsed())
    return false;
  return OwnerFrame()
      .GetFrame()
      ->GetDocument()
      ->Markers()
      .SetTextMatchMarkersActive(EphemeralRange(range), active);
}

void TextFinder::UnmarkAllTextMatches() {
  LocalFrame* frame = OwnerFrame().GetFrame();
  if (frame && frame->GetPage() &&
      frame->GetEditor().MarkedTextMatchesAreHighlighted()) {
    frame->GetDocument()->Markers().RemoveMarkersOfTypes(
        DocumentMarker::kTextMatch);
  }
}

bool TextFinder::ShouldScopeMatches(const String& search_text,
                                    const WebFindOptions& options) {
  // Don't scope if we can't find a frame or a view.
  // The user may have closed the tab/application, so abort.
  LocalFrame* frame = OwnerFrame().GetFrame();
  if (!frame || !frame->View() || !frame->GetPage())
    return false;

  DCHECK(frame->GetDocument());
  DCHECK(frame->View());

  if (options.force)
    return true;

  if (!OwnerFrame().HasVisibleContent())
    return false;

  // If the frame completed the scoping operation and found 0 matches the last
  // time it was searched, then we don't have to search it again if the user is
  // just adding to the search string or sending the same search string again.
  if (last_find_request_completed_with_no_matches_ &&
      !last_search_string_.IsEmpty()) {
    // Check to see if the search string prefixes match.
    String previous_search_prefix =
        search_text.Substring(0, last_search_string_.length());

    if (previous_search_prefix == last_search_string_)
      return false;  // Don't search this frame, it will be fruitless.
  }

  return true;
}

void TextFinder::ScopeStringMatchesSoon(int identifier,
                                        const WebString& search_text,
                                        const WebFindOptions& options) {
  DCHECK_EQ(deferred_scoping_work_, nullptr);
  deferred_scoping_work_ = DeferredScopeStringMatches::Create(
      this, identifier, search_text, options);
}

void TextFinder::ResumeScopingStringMatches(int identifier,
                                            const WebString& search_text,
                                            const WebFindOptions& options) {
  deferred_scoping_work_.Clear();

  ScopeStringMatches(identifier, search_text, options);
}

void TextFinder::InvalidateIfNecessary() {
  if (last_match_count_ <= next_invalidate_after_)
    return;

  // FIXME: (http://crbug.com/6819) Optimize the drawing of the tickmarks and
  // remove this. This calculation sets a milestone for when next to
  // invalidate the scrollbar and the content area. We do this so that we
  // don't spend too much time drawing the scrollbar over and over again.
  // Basically, up until the first 500 matches there is no throttle.
  // After the first 500 matches, we set set the milestone further and
  // further out (750, 1125, 1688, 2K, 3K).
  static const int kStartSlowingDownAfter = 500;
  static const int kSlowdown = 750;

  int i = last_match_count_ / kStartSlowingDownAfter;
  next_invalidate_after_ += i * kSlowdown;
  OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
}

void TextFinder::FlushCurrentScoping() {
  FlushCurrentScopingEffort(find_request_identifier_);
}

void TextFinder::Trace(blink::Visitor* visitor) {
  visitor->Trace(owner_frame_);
  visitor->Trace(active_match_);
  visitor->Trace(resume_scoping_from_range_);
  visitor->Trace(deferred_scoping_work_);
  visitor->Trace(find_matches_cache_);
}

}  // namespace blink
