OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ | 5 #ifndef CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ |
6 #define CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ | 6 #define CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ |
7 | 7 |
8 #include <set> | 8 #include <queue> |
| 9 #include <unordered_map> |
| 10 #include <unordered_set> |
| 11 #include <utility> |
9 #include <vector> | 12 #include <vector> |
10 | 13 |
| 14 #include "content/common/content_export.h" |
| 15 #include "content/public/browser/web_contents_observer.h" |
11 #include "content/public/common/stop_find_action.h" | 16 #include "content/public/common/stop_find_action.h" |
12 #include "third_party/WebKit/public/web/WebFindOptions.h" | 17 #include "third_party/WebKit/public/web/WebFindOptions.h" |
13 #include "ui/gfx/geometry/rect.h" | 18 #include "ui/gfx/geometry/rect.h" |
14 #include "ui/gfx/geometry/rect_f.h" | 19 #include "ui/gfx/geometry/rect_f.h" |
15 | 20 |
16 namespace content { | 21 namespace content { |
17 | 22 |
18 class RenderFrameHost; | 23 class RenderFrameHost; |
19 class WebContentsImpl; | 24 class WebContentsImpl; |
20 | 25 |
21 // FindRequestManager manages all of the find-in-page requests/replies | 26 // FindRequestManager manages all of the find-in-page requests/replies |
22 // initiated/received through a WebContents. It coordinates searching across | 27 // initiated/received through a WebContents. It coordinates searching across |
23 // multiple (potentially out-of-process) frames, handles the aggregation of find | 28 // multiple (potentially out-of-process) frames, handles the aggregation of find |
24 // results from each frame, and facilitates active match traversal. It is | 29 // results from each frame, and facilitates active match traversal. It is |
25 // instantiated once per WebContents, and is owned by that WebContents. | 30 // instantiated once per WebContents, and is owned by that WebContents. |
26 // | 31 class CONTENT_EXPORT FindRequestManager : public WebContentsObserver { |
27 // TODO(paulmeyer): FindRequestManager is currently incomplete and does not do | |
28 // all of these things yet, but will soon. | |
29 class FindRequestManager { | |
30 public: | 32 public: |
31 explicit FindRequestManager(WebContentsImpl* web_contents); | 33 explicit FindRequestManager(WebContentsImpl* web_contents); |
32 ~FindRequestManager(); | 34 ~FindRequestManager() override; |
33 | 35 |
34 // Initiates a find operation for |search_text| with the options specified in | 36 // Initiates a find operation for |search_text| with the options specified in |
35 // |options|. |request_id| uniquely identifies the find request. | 37 // |options|. |request_id| uniquely identifies the find request. |
36 void Find(int request_id, | 38 void Find(int request_id, |
37 const base::string16& search_text, | 39 const base::string16& search_text, |
38 const blink::WebFindOptions& options); | 40 const blink::WebFindOptions& options); |
39 | 41 |
40 // Stops the active find session and clears the general highlighting of the | 42 // Stops the active find session and clears the general highlighting of the |
41 // matches. |action| determines whether the last active match (if any) will be | 43 // matches. |action| determines whether the last active match (if any) will be |
42 // activated, cleared, or remain highlighted. | 44 // activated, cleared, or remain highlighted. |
43 void StopFinding(StopFindAction action); | 45 void StopFinding(StopFindAction action); |
44 | 46 |
45 // Called when a reply is received from a frame with the results from a | 47 // Called when a reply is received from a frame with the results from a |
46 // find request. | 48 // find request. |
47 void OnFindReply(RenderFrameHost* rfh, | 49 void OnFindReply(RenderFrameHost* rfh, |
48 int request_id, | 50 int request_id, |
49 int number_of_matches, | 51 int number_of_matches, |
50 const gfx::Rect& selection_rect, | 52 const gfx::Rect& selection_rect, |
51 int active_match_ordinal, | 53 int active_match_ordinal, |
52 bool final_update); | 54 bool final_update); |
53 | 55 |
| 56 // Removes a frame from the set of frames being searched. This should be |
| 57 // called whenever a frame is discovered to no longer exist. |
| 58 void RemoveFrame(RenderFrameHost* rfh); |
| 59 |
54 #if defined(OS_ANDROID) | 60 #if defined(OS_ANDROID) |
55 // Selects and zooms to the find result nearest to the point (x,y) defined in | 61 // Selects and zooms to the find result nearest to the point (x, y), defined |
56 // find-in-page coordinates. | 62 // in find-in-page coordinates. |
57 void ActivateNearestFindResult(float x, float y); | 63 void ActivateNearestFindResult(float x, float y); |
58 | 64 |
| 65 // Called when a reply is received from a frame in response to the |
| 66 // GetNearestFindResult IPC. |
| 67 void OnGetNearestFindResultReply(RenderFrameHost* rfh, |
| 68 int nearest_find_result_request_id, |
| 69 float distance); |
| 70 |
59 // Requests the rects of the current find matches from the renderer process. | 71 // Requests the rects of the current find matches from the renderer process. |
60 void RequestFindMatchRects(int current_version); | 72 void RequestFindMatchRects(int current_version); |
61 | 73 |
62 // Called when a reply is received in response to a request for find match | 74 // Called when a reply is received from a frame in response to a request for |
63 // rects. | 75 // find match rects. |
64 void OnFindMatchRectsReply(RenderFrameHost* rfh, | 76 void OnFindMatchRectsReply(RenderFrameHost* rfh, |
65 int version, | 77 int version, |
66 const std::vector<gfx::RectF>& rects, | 78 const std::vector<gfx::RectF>& rects, |
67 const gfx::RectF& active_rect); | 79 const gfx::RectF& active_rect); |
68 #endif | 80 #endif |
69 | 81 |
70 private: | 82 private: |
71 // An invalid ID. This value is invalid for any render process ID, render | 83 // An invalid ID. This value is invalid for any render process ID, render |
72 // frame ID, or find request ID. | 84 // frame ID, find request ID, or find match rects version number. |
73 static const int kInvalidId; | 85 static const int kInvalidId; |
74 | 86 |
75 // The request data for a single find request. | 87 // The request data for a single find request. |
76 struct FindRequest { | 88 struct FindRequest { |
77 // The find request ID that uniquely identifies this find request. | 89 // The find request ID that uniquely identifies this find request. |
78 int id = kInvalidId; | 90 int id = kInvalidId; |
79 | 91 |
80 // The text that is being searched for in this find request. | 92 // The text that is being searched for in this find request. |
81 base::string16 search_text; | 93 base::string16 search_text; |
82 | 94 |
83 // The set of find options in effect for this find request. | 95 // The set of find options in effect for this find request. |
84 blink::WebFindOptions options; | 96 blink::WebFindOptions options; |
85 | 97 |
86 FindRequest() = default; | 98 FindRequest() = default; |
87 FindRequest(int id, | 99 FindRequest(int id, |
88 const base::string16& search_text, | 100 const base::string16& search_text, |
89 const blink::WebFindOptions& options) | 101 const blink::WebFindOptions& options) |
90 : id(id), search_text(search_text), options(options) {} | 102 : id(id), search_text(search_text), options(options) {} |
91 }; | 103 }; |
92 | 104 |
93 // Send a find IPC containing the find request |request| to the RenderFrame | 105 // WebContentsObserver implementation. |
| 106 void RenderFrameDeleted(RenderFrameHost* rfh) override; |
| 107 void RenderFrameHostChanged(RenderFrameHost* old_host, |
| 108 RenderFrameHost* new_host) override; |
| 109 void FrameDeleted(RenderFrameHost* rfh) override; |
| 110 |
| 111 // Resets all of the per-session state for a new find-in-page session. |
| 112 void Reset(const FindRequest& initial_request); |
| 113 |
| 114 // Called internally as find requests come up in the queue. |
| 115 void FindInternal(const FindRequest& request); |
| 116 |
| 117 // Called when an informative response (a response with enough information to |
| 118 // be able to route subsequent find requests) comes in for the find request |
| 119 // with ID |request_id|. Advances the |find_request_queue_| if appropriate. |
| 120 void AdvanceQueue(int request_id); |
| 121 |
| 122 // Sends a find IPC containing the find request |request| to the RenderFrame |
94 // associated with |rfh|. | 123 // associated with |rfh|. |
95 void SendFindIPC(const FindRequest& request, RenderFrameHost* rfh); | 124 void SendFindIPC(const FindRequest& request, RenderFrameHost* rfh); |
96 | 125 |
97 // Send a stop finding IPC to the RenderFrame associated with |rfh|. | 126 // Sends the find results (as they currently are) to the WebContents. |
98 void SendStopFindingIPC(StopFindAction action, RenderFrameHost* rfh) const; | |
99 | |
100 // Reset all of the per-session state for a new find-in-page session. | |
101 void Reset(const FindRequest& initial_request); | |
102 | |
103 // Send the find results (as they currently are) to the WebContents. | |
104 void NotifyFindReply(int request_id, bool final_update) const; | 127 void NotifyFindReply(int request_id, bool final_update) const; |
105 | 128 |
| 129 // Returns the initial frame in search order. This will be either the first |
| 130 // frame, if searching forward, or the last frame, if searching backward. |
| 131 RenderFrameHost* GetInitialFrame(bool forward) const; |
| 132 |
| 133 // Traverses the frame tree to find and return the next RenderFrameHost after |
| 134 // |from_rfh| in search order. |forward| indicates whether the frame tree |
| 135 // should be traversed forward (if true) or backward (if false). If |
| 136 // |matches_only| is set, then the frame tree will be traversed until the |
| 137 // first frame is found for which matches have been found. If |wrap| is set, |
| 138 // then the traversal can wrap around past the last frame to the first one (or |
| 139 // vice-versa, if |forward| == false). If no frame can be found under these |
| 140 // conditions, nullptr is returned. |
| 141 RenderFrameHost* Traverse(RenderFrameHost* from_rfh, |
| 142 bool forward, |
| 143 bool matches_only, |
| 144 bool wrap) const; |
| 145 |
| 146 // Adds a frame to the set of frames that are being searched. The new frame |
| 147 // will automatically be searched when added, using the same options (stored |
| 148 // in |current_request_.options|). |
| 149 void AddFrame(RenderFrameHost* rfh); |
| 150 |
| 151 // Returns whether |rfh| is in the set of frames being searched in the current |
| 152 // find session. |
| 153 bool CheckFrame(RenderFrameHost* rfh) const; |
| 154 |
| 155 // Computes and updates |active_match_ordinal_| based on |active_frame_| and |
| 156 // |relative_active_match_ordinal_|. |
| 157 void UpdateActiveMatchOrdinal(); |
| 158 |
| 159 // Called when all pending find replies have been received for the find |
| 160 // request with ID |request_id|. The final update was received from |rfh|. |
| 161 void FinalUpdate(int request_id, RenderFrameHost* rfh); |
| 162 |
106 #if defined(OS_ANDROID) | 163 #if defined(OS_ANDROID) |
107 // Request the latest find match rects from a frame. | 164 // Called when a nearest find result reply is no longer pending for a frame. |
108 void SendFindMatchRectsIPC(RenderFrameHost* rfh); | 165 void RemoveNearestFindResultPendingReply(RenderFrameHost* rfh); |
| 166 |
| 167 // Called when a find match rects reply is no longer pending for a frame. |
| 168 void RemoveFindMatchRectsPendingReply(RenderFrameHost* rfh); |
| 169 |
| 170 // State related to ActivateNearestFindResult requests. |
| 171 struct ActivateNearestFindResultState { |
| 172 // An ID to uniquely identify the current nearest find result request and |
| 173 // its replies. |
| 174 int current_request_id = kInvalidId; |
| 175 |
| 176 // The x value of the requested point, in find-in-page coordinates. |
| 177 float x = 0.0f; |
| 178 |
| 179 // The y value of the requested point, in find-in-page coordinates. |
| 180 float y = 0.0f; |
| 181 |
| 182 // The distance to the nearest result found so far. |
| 183 float nearest_distance = FLT_MAX; |
| 184 |
| 185 // The frame containing the nearest result found so far. |
| 186 RenderFrameHost* nearest_frame = nullptr; |
| 187 |
| 188 // Nearest find result replies are still pending for these frames. |
| 189 std::unordered_set<RenderFrameHost*> pending_replies; |
| 190 |
| 191 ActivateNearestFindResultState(); |
| 192 ActivateNearestFindResultState(float x, float y); |
| 193 ~ActivateNearestFindResultState(); |
| 194 |
| 195 static int GetNextID() { |
| 196 static int next_id = 0; |
| 197 return next_id++; |
| 198 } |
| 199 } activate_; |
| 200 |
| 201 // Data for find match rects in a single frame. |
| 202 struct FrameRects { |
| 203 // The rects contained in a single frame. |
| 204 std::vector<gfx::RectF> rects; |
| 205 |
| 206 // The version number for these rects, as reported by their containing |
| 207 // frame. This version is incremented independently in each frame. |
| 208 int version = kInvalidId; |
| 209 |
| 210 FrameRects(); |
| 211 FrameRects(const std::vector<gfx::RectF>& rects, int version); |
| 212 ~FrameRects(); |
| 213 }; |
109 | 214 |
110 // State related to FindMatchRects requests. | 215 // State related to FindMatchRects requests. |
111 struct FindMatchRectsState { | 216 struct FindMatchRectsState { |
112 // The latest find match rects version known by the requester. | 217 // The latest find match rects version known by the requester. This will be |
| 218 // compared to |known_version_| after polling frames for updates to their |
| 219 // match rects, in order to determine if the requester already has the |
| 220 // latest version of rects or not. |
113 int request_version = kInvalidId; | 221 int request_version = kInvalidId; |
| 222 |
| 223 // The current overall find match rects version known by |
| 224 // FindRequestManager. This version should be incremented whenever |
| 225 // |frame_rects| is updated. |
| 226 int known_version = 0; |
| 227 |
| 228 // A map from each frame to its find match rects. |
| 229 std::unordered_map<RenderFrameHost*, FrameRects> frame_rects; |
| 230 |
| 231 // The active find match rect. |
| 232 gfx::RectF active_rect; |
| 233 |
| 234 // Find match rects replies are still pending for these frames. |
| 235 std::unordered_set<RenderFrameHost*> pending_replies; |
| 236 |
| 237 FindMatchRectsState(); |
| 238 ~FindMatchRectsState(); |
114 } match_rects_; | 239 } match_rects_; |
115 #endif | 240 #endif |
116 | 241 |
117 // The WebContents that owns this FindRequestManager. | 242 // The WebContents that owns this FindRequestManager. |
118 WebContentsImpl* const contents_; | 243 WebContentsImpl* const contents_; |
119 | 244 |
120 // The request ID of the initial find request in the current find-in-page | 245 // The request ID of the initial find request in the current find-in-page |
121 // session, which uniquely identifies this session. Request IDs are included | 246 // session, which uniquely identifies this session. Request IDs are included |
122 // in all find-related IPCs, which allows reply IPCs containing results from | 247 // in all find-related IPCs, which allows reply IPCs containing results from |
123 // previous sessions (with |request_id| < |current_session_id_|) to be easily | 248 // previous sessions (with |request_id| < |current_session_id_|) to be easily |
124 // identified and ignored. | 249 // identified and ignored. |
125 int current_session_id_; | 250 int current_session_id_; |
126 | 251 |
127 // The current find request. | 252 // The current find request. |
128 FindRequest current_request_; | 253 FindRequest current_request_; |
129 | 254 |
130 // The total number of matches found in the current find-in-page session. | 255 // The set of frames that are still expected to reply to a pending find |
| 256 // request. Frames are removed from |pending_replies_| when their reply with |
| 257 // |final_update| set to true is received. |
| 258 std::unordered_set<RenderFrameHost*> pending_replies_; |
| 259 |
| 260 // Indicates whether an update to the active match ordinal is expected. Once |
| 261 // set, |pending_active_match_ordinal_| will not reset until an update to the |
| 262 // active match ordinal is received in response to the find request with ID |
| 263 // |current_request_.id| (the latest request). |
| 264 bool pending_active_match_ordinal_; |
| 265 |
| 266 // The number of matches found in each frame. There will necessarily be |
| 267 // entries in this map for every frame that is being (or has been) searched in |
| 268 // the current find session, and no other frames. |
| 269 std::unordered_map<RenderFrameHost*, int> matches_per_frame_; |
| 270 |
| 271 // The total number of matches found in the current find-in-page session. This |
| 272 // should always be equal to the sum of all the entries in |
| 273 // |matches_per_frame_|. |
131 int number_of_matches_; | 274 int number_of_matches_; |
132 | 275 |
| 276 // The frame containing the active match, if one exists, or nullptr otherwise. |
| 277 RenderFrameHost* active_frame_; |
| 278 |
| 279 // The active match ordinal relative to the matches found in its own frame. |
| 280 int relative_active_match_ordinal_; |
| 281 |
133 // The overall active match ordinal for the current find-in-page session. | 282 // The overall active match ordinal for the current find-in-page session. |
134 int active_match_ordinal_; | 283 int active_match_ordinal_; |
135 | 284 |
136 // The rectangle around the active match, in screen coordinates. | 285 // The rectangle around the active match, in screen coordinates. |
137 gfx::Rect selection_rect_; | 286 gfx::Rect selection_rect_; |
| 287 |
| 288 // Find requests are queued here when previous requests need to be handled |
| 289 // before these ones can be properly routed. |
| 290 std::queue<FindRequest> find_request_queue_; |
138 }; | 291 }; |
139 | 292 |
140 } // namespace content | 293 } // namespace content |
141 | 294 |
142 #endif // CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ | 295 #endif // CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_ |
OLD | NEW |