// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_
#define CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_

#include <cfloat>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "base/cancelable_callback.h"
#include "base/containers/queue.h"
#include "base/functional/function_ref.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/stop_find_action.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"

namespace content {

class FindInPageClient;
class RenderFrameHost;
class RenderFrameHostImpl;
class WebContentsImpl;

// FindRequestManager manages all of the find-in-page requests/replies
// initiated/received through a WebContents. It coordinates searching across
// multiple (potentially out-of-process) frames, handles the aggregation of find
// results from each frame, and facilitates active match traversal. It is
// instantiated once per top-level WebContents, and is owned by that
// WebContents.
class FindRequestManager {
 public:
  explicit FindRequestManager(WebContentsImpl* web_contents);

  FindRequestManager(const FindRequestManager&) = delete;
  FindRequestManager& operator=(const FindRequestManager&) = delete;

  ~FindRequestManager();

  // Initiates a find operation for |search_text| with the options specified in
  // |options|. |request_id| uniquely identifies the find request.
  void Find(int request_id,
            const std::u16string& search_text,
            blink::mojom::FindOptionsPtr options,
            bool skip_delay = false);

  // Stops the active find session and clears the general highlighting of the
  // matches. |action| determines whether the last active match (if any) will be
  // activated, cleared, or remain highlighted.
  void StopFinding(StopFindAction action);

  // Handles the final update from |rfh| for the find request with id
  // |request_id|.
  void HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh, int request_id);

  // The number of matches on |rfh| has changed from |old_count| to |new_count|.
  // This method updates the total number of matches and also updates
  // |active_match_ordinal_| accordingly.
  void UpdatedFrameNumberOfMatches(RenderFrameHostImpl* rfh,
                                   unsigned int old_count,
                                   unsigned int new_count);

  bool ShouldIgnoreReply(RenderFrameHostImpl* rfh, int request_id);

  void SetActiveMatchRect(const gfx::Rect& active_match_rect);

  void SetActiveMatchOrdinal(RenderFrameHostImpl* rfh,
                             int request_id,
                             int active_match_ordinal);

  // Sends the find results (as they currently are) to the WebContents.
  // |final_update| is true if we have received all of the updates from
  // every frame for this request.
  void NotifyFindReply(int request_id, bool final_update);

  // Removes a frame from the set of frames being searched. This should be
  // called whenever a frame is discovered to no longer exist.
  void RemoveFrame(RenderFrameHost* rfh);

  // Tells active frame to clear the active match highlighting.
  void ClearActiveFindMatch();

  // Runs the delayed find task if present. Returns true if there was a task
  // which got run. Returns false if there was no delayed task.
  bool CONTENT_EXPORT RunDelayedFindTaskForTesting();

#if BUILDFLAG(IS_ANDROID)
  // Selects and zooms to the find result nearest to the point (x, y), defined
  // in find-in-page coordinates.
  void ActivateNearestFindResult(float x, float y);

  // Called when a reply is received from a frame in response to the
  // GetNearestFindResult mojo call.
  void OnGetNearestFindResultReply(RenderFrameHostImpl* rfh,
                                   int request_id,
                                   float distance);

  // Requests the rects of the current find matches from the renderer process.
  void RequestFindMatchRects(int current_version);

  // Called when a reply is received from a frame in response to a request for
  // find match rects.
  void OnFindMatchRectsReply(RenderFrameHost* rfh,
                             int version,
                             const std::vector<gfx::RectF>& rects,
                             const gfx::RectF& active_rect);
#endif

  const std::unordered_set<raw_ptr<RenderFrameHost, CtnExperimental>>
  render_frame_hosts_pending_initial_reply_for_testing() const {
    return pending_initial_replies_;
  }

  gfx::Rect GetSelectionRectForTesting() { return selection_rect_; }

  using CreateFindInPageClientFunction = std::unique_ptr<FindInPageClient> (*)(
      FindRequestManager* find_request_manager,
      RenderFrameHostImpl* rfh);
  void SetCreateFindInPageClientFunctionForTesting(
      CreateFindInPageClientFunction create_func) {
    create_find_in_page_client_for_testing_ = create_func;
  }

 private:
  friend class FindRequestManagerFencedFrameTest;

  // An invalid ID. This value is invalid for any render process ID, render
  // frame ID, find request ID, or find match rects version number.
  static const int kInvalidId;

  class FrameObserver;

  // The request data for a single find request.
  struct FindRequest {
    // The find request ID that uniquely identifies this find request.
    int id = kInvalidId;

    // The text that is being searched for in this find request.
    std::u16string search_text;

    // The set of find options in effect for this find request.
    blink::mojom::FindOptionsPtr options;

    FindRequest();
    FindRequest(int id,
                const std::u16string& search_text,
                blink::mojom::FindOptionsPtr options);
    FindRequest(const FindRequest& request);
    ~FindRequest();

    FindRequest& operator=(const FindRequest& request);
  };

  // Resets all of the per-session state for a new find-in-page session.
  void Reset(const FindRequest& initial_request);

  // Called internally as find requests come up in the queue.
  void FindInternal(const FindRequest& request);

  // Called when an informative response (a response with enough information to
  // be able to route subsequent find requests) comes in for the find request
  // with ID |request_id|. Advances the |find_request_queue_| if appropriate.
  void AdvanceQueue(int request_id);

  // Sends find request |request| through mojo to the RenderFrame associated
  // with |rfh|.
  void SendFindRequest(const FindRequest& request, RenderFrameHost* rfh);

  // Returns the initial frame in search order. This will be either the first
  // frame, if searching forward, or the last frame, if searching backward.
  RenderFrameHost* GetInitialFrame(bool forward) const;

  // Traverses the frame tree to find and return the next RenderFrameHost after
  // |from_rfh| in search order. |forward| indicates whether the frame tree
  // should be traversed forward (if true) or backward (if false). If
  // |matches_only| is set, then the frame tree will be traversed until the
  // first frame is found for which matches have been found. If |wrap| is set,
  // then the traversal can wrap around past the last frame to the first one (or
  // vice-versa, if |forward| == false). If no frame can be found under these
  // conditions, nullptr is returned.
  RenderFrameHost* Traverse(RenderFrameHost* from_rfh,
                            bool forward,
                            bool matches_only,
                            bool wrap) const;

  // Adds a frame to the set of frames that are being searched. The new frame
  // will automatically be searched when added, using the same options (stored
  // in |current_request_.options|). |force| should be set to true when a
  // dynamic content change is suspected, which will treat the frame as a newly
  // added frame even if it has already been searched. This will force a
  // re-search of the frame.
  void AddFrame(RenderFrameHost* rfh, bool force);

  // Returns whether |rfh| is in the set of frames being searched in the current
  // find session.
  CONTENT_EXPORT bool CheckFrame(RenderFrameHost* rfh) const;

  // Computes and updates |active_match_ordinal_| based on |active_frame_| and
  // |relative_active_match_ordinal_|.
  void UpdateActiveMatchOrdinal();

  // Called when all pending find replies have been received for the find
  // request with ID |request_id|. The final update was received from |rfh|.
  //
  // Note that this is the final update for this particular find request, but
  // not necessarily for all issued requests. If there are still pending replies
  // expected for a previous find request, then the outgoing find reply issued
  // from this function will not be marked final.
  void FinalUpdateReceived(int request_id, RenderFrameHost* rfh);

  std::unique_ptr<FindInPageClient> CreateFindInPageClient(
      RenderFrameHostImpl* rfh);

  // Traverses all RenderFrameHosts added for find-in-page and invokes the
  // callback if the each RenderFrameHost is alive and active.
  void ForEachAddedFindInPageRenderFrameHost(
      base::FunctionRef<void(RenderFrameHostImpl*)> func_ref);

  void EmitFindRequest(int request_id,
                       const std::u16string& search_text,
                       blink::mojom::FindOptionsPtr options);

#if BUILDFLAG(IS_ANDROID)
  // Called when a nearest find result reply is no longer pending for a frame.
  void RemoveNearestFindResultPendingReply(RenderFrameHost* rfh);

  // Called when a find match rects reply is no longer pending for a frame.
  void RemoveFindMatchRectsPendingReply(RenderFrameHost* rfh);

  // State related to ActivateNearestFindResult requests.
  struct ActivateNearestFindResultState {
    // An ID to uniquely identify the current nearest find result request and
    // its replies.
    int current_request_id = kInvalidId;

    // The value of the requested point, in find-in-page coordinates.
    gfx::PointF point = gfx::PointF(0.0f, 0.0f);

    float nearest_distance = FLT_MAX;

    // The frame containing the nearest result found so far.
    raw_ptr<RenderFrameHostImpl> nearest_frame = nullptr;

    // Nearest find result replies are still pending for these frames.
    std::unordered_set<raw_ptr<RenderFrameHost, CtnExperimental>>
        pending_replies;

    ActivateNearestFindResultState();
    ActivateNearestFindResultState(float x, float y);
    ~ActivateNearestFindResultState();

    static int GetNextID();

  } activate_;

  // Data for find match rects in a single frame.
  struct FrameRects {
    // The rects contained in a single frame.
    std::vector<gfx::RectF> rects;

    // The version number for these rects, as reported by their containing
    // frame. This version is incremented independently in each frame.
    int version = kInvalidId;

    FrameRects();
    FrameRects(const std::vector<gfx::RectF>& rects, int version);
    ~FrameRects();
  };

  // State related to FindMatchRects requests.
  struct FindMatchRectsState {
    // The latest find match rects version known by the requester. This will be
    // compared to |known_version_| after polling frames for updates to their
    // match rects, in order to determine if the requester already has the
    // latest version of rects or not.
    int request_version = kInvalidId;

    // The current overall find match rects version known by
    // FindRequestManager. This version should be incremented whenever
    // |frame_rects| is updated.
    int known_version = 0;

    // A map from each frame to its find match rects.
    std::unordered_map<RenderFrameHost*, FrameRects> frame_rects;

    // The active find match rect.
    gfx::RectF active_rect;

    // Find match rects replies are still pending for these frames.
    std::unordered_set<raw_ptr<RenderFrameHost, CtnExperimental>>
        pending_replies;

    FindMatchRectsState();
    ~FindMatchRectsState();
  } match_rects_;
#endif

  // The WebContents that owns this FindRequestManager. This also defines the
  // scope of all find sessions. Only frames in |contents_| and any inner
  // WebContentses within it will be searched.
  const raw_ptr<WebContentsImpl> contents_;

  // The request ID of the initial find request in the current find-in-page
  // session, which uniquely identifies this session. Request IDs are included
  // in all find-related IPCs, which allows reply IPCs containing results from
  // previous sessions (with |request_id| < |current_session_id_|) to be easily
  // identified and ignored.
  int current_session_id_ = kInvalidId;

  // The current find request.
  FindRequest current_request_;

  // The set of frames that are still expected to reply to a pending initial
  // find request. Frames are removed from |pending_initial_replies_| when their
  // reply to the initial find request is received with |final_update| set to
  // true.
  std::unordered_set<raw_ptr<RenderFrameHost, CtnExperimental>>
      pending_initial_replies_;

  // The frame (if any) that is still expected to reply to the last pending
  // "find next" request.
  raw_ptr<RenderFrameHost> pending_find_next_reply_ = nullptr;

  // Indicates whether an update to the active match ordinal is expected. Once
  // set, |pending_active_match_ordinal_| will not reset until an update to the
  // active match ordinal is received in response to the find request with ID
  // |current_request_.id| (the latest request).
  bool pending_active_match_ordinal_ = false;

  // The FindInPageClient associated with each frame. There will necessarily be
  // entries in this map for every frame that is being (or has been) searched in
  // the current find session, and no other frames.
  std::unordered_map<RenderFrameHost*, std::unique_ptr<FindInPageClient>>
      find_in_page_clients_;

  // The total number of matches found in the current find-in-page session. This
  // should always be equal to the sum of all the entries in
  // |matches_per_frame_|.
  int number_of_matches_ = 0;

  // The frame containing the active match, if one exists, or nullptr otherwise.
  raw_ptr<RenderFrameHostImpl> active_frame_ = nullptr;

  // The active match ordinal relative to the matches found in its own frame.
  int relative_active_match_ordinal_ = 0;

  // The overall active match ordinal for the current find-in-page session.
  int active_match_ordinal_ = 0;

  // The rectangle around the active match, in screen coordinates.
  gfx::Rect selection_rect_;

  // Find requests are queued here when previous requests need to be handled
  // before these ones can be properly routed.
  base::queue<FindRequest> find_request_queue_;

  // Keeps track of the find request ID of the last find reply reported via
  // NotifyFindReply().
  int last_reported_id_ = kInvalidId;

  // WebContentsObservers to observe frame changes in |contents_| and its inner
  // WebContentses.
  std::vector<std::unique_ptr<FrameObserver>> frame_observers_;

  base::CancelableOnceClosure delayed_find_task_;

  CreateFindInPageClientFunction create_find_in_page_client_for_testing_ =
      nullptr;

  base::WeakPtrFactory<FindRequestManager> weak_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_
