
This histogram isn't needed anymore now that we have shipped auto-expanding details and hidden=until-found. This effectively reverts crrev.com/924007 Fixed: 333390100 Bug: 40197893 Change-Id: I9f5c2773d9440676ce13e085114b59d1522d854a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5519293 Reviewed-by: Chris Harrelson <chrishtr@chromium.org> Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Commit-Queue: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1297260}
385 lines
15 KiB
C++
385 lines
15 KiB
C++
// 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 <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() {
|
|
static int next_id = 0;
|
|
return next_id++;
|
|
}
|
|
} 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_
|