Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: content/browser/find_request_manager.cc

Issue 1959183002: Multi-Process Find-in-Page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments by nick@. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "content/browser/find_request_manager.h" 5 #include "content/browser/find_request_manager.h"
6 6
7 #include "content/browser/frame_host/render_frame_host_impl.h" 7 #include "content/browser/frame_host/render_frame_host_impl.h"
8 #include "content/browser/web_contents/web_contents_impl.h" 8 #include "content/browser/web_contents/web_contents_impl.h"
9 #include "content/common/frame_messages.h" 9 #include "content/common/frame_messages.h"
10 #include "content/common/input_messages.h" 10 #include "content/common/input_messages.h"
11 11
12 namespace content { 12 namespace content {
13 13
14 namespace {
15
16 // Returns the deepest last child frame under |node|/|rfh| in the frame tree.
17 FrameTreeNode* GetDeepestLastChild(FrameTreeNode* node) {
18 while (node->child_count())
19 node = node->child_at(node->child_count() - 1);
20 return node;
21 }
22 RenderFrameHost* GetDeepestLastChild(RenderFrameHost* rfh) {
23 FrameTreeNode* node =
24 static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
25 return GetDeepestLastChild(node)->current_frame_host();
26 }
27
28 // Returns the FrameTreeNode directly after |node| in the frame tree in search
29 // order, or nullptr if one does not exist. If |wrap| is set, then wrapping
30 // between the first and last frames is permitted. Note that this traversal
31 // follows the same ordering as in blink::FrameTree::traverseNextWithWrap().
32 FrameTreeNode* TraverseNext(FrameTreeNode* node, bool wrap) {
33 if (node->child_count())
34 return node->child_at(0);
35
36 FrameTreeNode* sibling = node->NextSibling();
37 while (!sibling) {
38 if (!node->parent())
39 return wrap ? node : nullptr;
40 node = node->parent();
41 sibling = node->NextSibling();
42 }
43 return sibling;
44 }
45
46 // Returns the FrameTreeNode directly before |node| in the frame tree in search
47 // order, or nullptr if one does not exist. If |wrap| is set, then wrapping
48 // between the first and last frames is permitted. Note that this traversal
49 // follows the same ordering as in blink::FrameTree::traversePreviousWithWrap().
50 FrameTreeNode* TraversePrevious(FrameTreeNode* node, bool wrap) {
51 if (FrameTreeNode* previous_sibling = node->PreviousSibling())
52 return GetDeepestLastChild(previous_sibling);
53 if (node->parent())
54 return node->parent();
55 return wrap ? GetDeepestLastChild(node) : nullptr;
56 }
57
58 // The same as either TraverseNext() or TraversePrevious() depending on
59 // |forward|.
60 FrameTreeNode* TraverseNode(FrameTreeNode* node, bool forward, bool wrap) {
61 return forward ? TraverseNext(node, wrap) : TraversePrevious(node, wrap);
62 }
63
64 } // namespace
65
66 #if defined(OS_ANDROID)
67 FindRequestManager::ActivateNearestFindResultState::
68 ActivateNearestFindResultState() = default;
69 FindRequestManager::ActivateNearestFindResultState::
70 ActivateNearestFindResultState(float x, float y)
71 : current_request_id(GetNextID()),
72 x(x),
73 y(y) {}
74 FindRequestManager::ActivateNearestFindResultState::
75 ~ActivateNearestFindResultState() {}
76
77 FindRequestManager::FrameRects::FrameRects() = default;
78 FindRequestManager::FrameRects::FrameRects(const std::vector<gfx::RectF>& rects,
79 int version)
80 : rects(rects), version(version) {}
81 FindRequestManager::FrameRects::~FrameRects() {}
82
83 FindRequestManager::FindMatchRectsState::FindMatchRectsState() = default;
84 FindRequestManager::FindMatchRectsState::~FindMatchRectsState() {}
85 #endif
86
14 // static 87 // static
15 const int FindRequestManager::kInvalidId = -1; 88 const int FindRequestManager::kInvalidId = -1;
16 89
17 FindRequestManager::FindRequestManager(WebContentsImpl* web_contents) 90 FindRequestManager::FindRequestManager(WebContentsImpl* web_contents)
18 : contents_(web_contents), 91 : WebContentsObserver(web_contents),
92 contents_(web_contents),
19 current_session_id_(kInvalidId), 93 current_session_id_(kInvalidId),
94 pending_active_match_ordinal_(false),
20 number_of_matches_(0), 95 number_of_matches_(0),
96 active_frame_(nullptr),
97 relative_active_match_ordinal_(0),
21 active_match_ordinal_(0) {} 98 active_match_ordinal_(0) {}
22 99
23 FindRequestManager::~FindRequestManager() {} 100 FindRequestManager::~FindRequestManager() {}
24 101
25 void FindRequestManager::Find(int request_id, 102 void FindRequestManager::Find(int request_id,
26 const base::string16& search_text, 103 const base::string16& search_text,
27 const blink::WebFindOptions& options) { 104 const blink::WebFindOptions& options) {
28 // Every find request must have a unique ID, and these IDs must strictly 105 // Every find request must have a unique ID, and these IDs must strictly
29 // increase so that newer requests always have greater IDs than older 106 // increase so that newer requests always have greater IDs than older
30 // requests. 107 // requests.
31 DCHECK_GT(request_id, current_request_.id); 108 DCHECK_GT(request_id, current_request_.id);
32 DCHECK_GT(request_id, current_session_id_); 109 DCHECK_GT(request_id, current_session_id_);
33 110
34 FindRequest request(request_id, search_text, options); 111 // If this is a new find session, clear any queued requests from last session.
35 112 if (!options.findNext) {
36 if (options.findNext) { 113 find_request_queue_ = std::queue<FindRequest>();
37 // This is a find next operation.
38
39 // This implies that there is an ongoing find session with the same search
40 // text.
41 DCHECK_GE(current_session_id_, 0);
42 DCHECK_EQ(request.search_text, current_request_.search_text);
43
44 current_request_ = request;
45 } else {
46 // This is an initial find operation.
47 Reset(request);
48 } 114 }
49 115
50 SendFindIPC(request, contents_->GetMainFrame()); 116 find_request_queue_.emplace(request_id, search_text, options);
117 if (find_request_queue_.size() == 1)
118 FindInternal(find_request_queue_.front());
51 } 119 }
52 120
53 void FindRequestManager::StopFinding(StopFindAction action) { 121 void FindRequestManager::StopFinding(StopFindAction action) {
54 SendStopFindingIPC(action, contents_->GetMainFrame()); 122 contents_->SendToAllFrames(
123 new FrameMsg_StopFinding(MSG_ROUTING_NONE, action));
124
55 current_session_id_ = kInvalidId; 125 current_session_id_ = kInvalidId;
126 #if defined(OS_ANDROID)
127 // It is important that these pending replies are cleared whenever a find
128 // session ends, so that subsequent replies for the old session are ignored.
129 match_rects_.pending_replies.clear();
130 #endif
56 } 131 }
57 132
58 void FindRequestManager::OnFindReply(RenderFrameHost* rfh, 133 void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
59 int request_id, 134 int request_id,
60 int number_of_matches, 135 int number_of_matches,
61 const gfx::Rect& selection_rect, 136 const gfx::Rect& selection_rect,
62 int active_match_ordinal, 137 int active_match_ordinal,
63 bool final_update) { 138 bool final_update) {
64 // Ignore stale replies from abandoned find sessions. 139 // Ignore stale replies from abandoned find sessions.
65 if (current_session_id_ == kInvalidId || request_id < current_session_id_) 140 if (current_session_id_ == kInvalidId || request_id < current_session_id_)
66 return; 141 return;
142 DCHECK(CheckFrame(rfh));
67 143
68 // Update the stored results. 144 // Update the stored find results.
69 number_of_matches_ = number_of_matches;
70 selection_rect_ = selection_rect;
71 active_match_ordinal_ = active_match_ordinal;
72 145
73 NotifyFindReply(request_id, final_update); 146 DCHECK_GE(number_of_matches, -1);
147 DCHECK_GE(active_match_ordinal, -1);
148
149 // Check for an update to the number of matches.
150 if (number_of_matches != -1) {
151 DCHECK_GE(number_of_matches, 0);
152 // Increment the global number of matches by the number of additional
153 // matches found for this frame.
154 auto matches_per_frame_it = matches_per_frame_.find(rfh);
155 number_of_matches_ += number_of_matches - matches_per_frame_it->second;
156 matches_per_frame_it->second = number_of_matches;
157 }
158
159 // Check for an update to the selection rect.
160 if (!selection_rect.IsEmpty())
161 selection_rect_ = selection_rect;
162
163 // Check for an update to the active match ordinal.
164 if (active_match_ordinal > 0) {
165 if (rfh == active_frame_) {
166 active_match_ordinal_ +=
167 active_match_ordinal - relative_active_match_ordinal_;
168 relative_active_match_ordinal_ = active_match_ordinal;
169 } else {
170 if (active_frame_) {
171 // The new active match is in a different frame than the previous, so
172 // the previous active frame needs to be informed (to clear its active
173 // match highlighting).
174 active_frame_->Send(new FrameMsg_ClearActiveFindMatch(
175 active_frame_->GetRoutingID()));
176 }
177 active_frame_ = rfh;
178 relative_active_match_ordinal_ = active_match_ordinal;
179 UpdateActiveMatchOrdinal();
180 }
181 if (pending_active_match_ordinal_ && request_id == current_request_.id)
182 pending_active_match_ordinal_ = false;
183 AdvanceQueue(request_id);
184 }
185
186 if (!final_update) {
187 NotifyFindReply(request_id, false /* final_update */);
188 return;
189 }
190
191 // This is the final update for this frame for the current find operation.
192
193 pending_replies_.erase(rfh);
194 if (request_id == current_session_id_ && !pending_replies_.empty()) {
195 NotifyFindReply(request_id, false /* final_update */);
196 return;
197 }
198 DCHECK(request_id == current_session_id_ ||
199 current_request_.options.findNext);
200
201 // This is the final update for the current find operation.
202 FinalUpdate(request_id, rfh);
203 }
204
205 void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
206 if (current_session_id_ == kInvalidId || !CheckFrame(rfh))
207 return;
208
209 if (pending_replies_.count(rfh)) {
210 // A reply should not be expected from the removed frame.
211 pending_replies_.erase(rfh);
212 if (pending_replies_.empty())
213 FinalUpdate(current_session_id_, rfh);
214 }
215
216 #if defined(OS_ANDROID)
217 // A reply should not be expected from the removed frame.
ncarter (slow) 2016/05/31 21:07:31 What if activate_.nearest_frame == rfh at this poi
paulmeyer 2016/06/01 19:22:06 I think it actually works without clearing it here
218 RemoveNearestFindResultPendingReply(rfh);
219 RemoveFindMatchRectsPendingReply(rfh);
220
221 // Match rects in the removed frame are no longer relevant.
222 match_rects_.frame_rects.erase(rfh);
223 #endif
224
225 // If matches are counted for the frame that is being removed, decrement the
226 // match total before erasing that entry.
227 auto it = matches_per_frame_.find(rfh);
228 if (it != matches_per_frame_.end()) {
229 number_of_matches_ -= it->second;
230 matches_per_frame_.erase(it);
231 }
232
233 // Update the active match ordinal, since it may have changed.
234 if (active_frame_ == rfh) {
235 active_frame_ = nullptr;
236 relative_active_match_ordinal_ = 0;
237 }
238 UpdateActiveMatchOrdinal();
239
240 NotifyFindReply(current_session_id_,
241 pending_replies_.empty() /* final_update */);
74 } 242 }
75 243
76 #if defined(OS_ANDROID) 244 #if defined(OS_ANDROID)
77 void FindRequestManager::ActivateNearestFindResult(float x, 245 void FindRequestManager::ActivateNearestFindResult(float x,
78 float y) { 246 float y) {
79 if (current_session_id_ == kInvalidId) 247 if (current_session_id_ == kInvalidId)
80 return; 248 return;
81 249
82 auto rfh = contents_->GetMainFrame(); 250 activate_ = ActivateNearestFindResultState(x, y);
83 rfh->Send(new InputMsg_ActivateNearestFindResult( 251
84 rfh->GetRoutingID(), current_session_id_, x, y)); 252 // Request from each frame the distance to the nearest find result (in that
253 // frame) from the point (x, y), defined in find-in-page coordinates.
254 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
255 RenderFrameHost* rfh = node->current_frame_host();
256
257 if (!CheckFrame(rfh))
258 continue;
259
260 activate_.pending_replies.insert(rfh);
261 rfh->Send(new FrameMsg_GetNearestFindResult(
262 rfh->GetRoutingID(), activate_.current_request_id,
263 activate_.x, activate_.y));
264 }
265 }
266
267 void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh,
268 int request_id,
269 float distance) {
270 if (request_id != activate_.current_request_id ||
271 !activate_.pending_replies.count(rfh)) {
272 return;
273 }
274
275 // Check if this frame has a nearer find result than the current nearest.
276 if (distance < activate_.nearest_distance) {
277 activate_.nearest_frame = rfh;
278 activate_.nearest_distance = distance;
279 }
280
281 RemoveNearestFindResultPendingReply(rfh);
85 } 282 }
86 283
87 void FindRequestManager::RequestFindMatchRects(int current_version) { 284 void FindRequestManager::RequestFindMatchRects(int current_version) {
285 match_rects_.pending_replies.clear();
88 match_rects_.request_version = current_version; 286 match_rects_.request_version = current_version;
89 SendFindMatchRectsIPC(contents_->GetMainFrame()); 287
288 // Request the latest find match rects from each frame.
289 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
290 RenderFrameHost* rfh = node->current_frame_host();
291
292 if (!CheckFrame(rfh))
293 continue;
294
295 match_rects_.pending_replies.insert(rfh);
296 auto it = match_rects_.frame_rects.find(rfh);
297 int version = (it != match_rects_.frame_rects.end())
298 ? it->second.version : kInvalidId;
299 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version));
300 }
90 } 301 }
91 302
92 void FindRequestManager::OnFindMatchRectsReply( 303 void FindRequestManager::OnFindMatchRectsReply(
93 RenderFrameHost* rfh, 304 RenderFrameHost* rfh,
94 int version, 305 int version,
95 const std::vector<gfx::RectF>& rects, 306 const std::vector<gfx::RectF>& rects,
96 const gfx::RectF& active_rect) { 307 const gfx::RectF& active_rect) {
97 contents_->NotifyFindMatchRectsReply(version, rects, active_rect); 308 auto it = match_rects_.frame_rects.find(rfh);
309 if (it == match_rects_.frame_rects.end() || it->second.version != version) {
310 // New version of rects has been received, so update the data.
311 match_rects_.frame_rects[rfh] = FrameRects(rects, version);
312 ++match_rects_.known_version;
313 }
314 if (!active_rect.IsEmpty())
315 match_rects_.active_rect = active_rect;
316 RemoveFindMatchRectsPendingReply(rfh);
98 } 317 }
99 #endif 318 #endif
100 319
320 void FindRequestManager::RenderFrameDeleted(RenderFrameHost* rfh) {
321 RemoveFrame(rfh);
322 }
323
324 void FindRequestManager::RenderFrameHostChanged(RenderFrameHost* old_host,
325 RenderFrameHost* new_host) {
326 RemoveFrame(old_host);
327 }
328
329 void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) {
330 RemoveFrame(rfh);
331 }
332
101 void FindRequestManager::Reset(const FindRequest& initial_request) { 333 void FindRequestManager::Reset(const FindRequest& initial_request) {
102 current_session_id_ = initial_request.id; 334 current_session_id_ = initial_request.id;
103 current_request_ = initial_request; 335 current_request_ = initial_request;
336 pending_replies_.clear();
337 pending_active_match_ordinal_ = true;
338 matches_per_frame_.clear();
104 number_of_matches_ = 0; 339 number_of_matches_ = 0;
340 active_frame_ = nullptr;
341 relative_active_match_ordinal_ = 0;
105 active_match_ordinal_ = 0; 342 active_match_ordinal_ = 0;
106 selection_rect_ = gfx::Rect(); 343 selection_rect_ = gfx::Rect();
107 #if defined(OS_ANDROID) 344 #if defined(OS_ANDROID)
108 match_rects_ = FindMatchRectsState(); 345 activate_ = ActivateNearestFindResultState();
346 match_rects_.pending_replies.clear();
109 #endif 347 #endif
110 } 348 }
111 349
350 void FindRequestManager::FindInternal(const FindRequest& request) {
351 DCHECK_GT(request.id, current_request_.id);
352 DCHECK_GT(request.id, current_session_id_);
353
354 if (request.options.findNext) {
355 // This is a find next operation.
356
357 // This implies that there is an ongoing find session with the same search
358 // text.
359 DCHECK_GE(current_session_id_, 0);
360 DCHECK_EQ(request.search_text, current_request_.search_text);
361
362 // The find next request will be directed at the focused frame if there is
363 // one, or the first frame with matches otherwise.
364 RenderFrameHost* target_rfh = contents_->GetFocusedFrame();
365 if (!target_rfh || !CheckFrame(target_rfh))
366 target_rfh = GetInitialFrame(request.options.forward);
367
368 SendFindIPC(request, target_rfh);
369 current_request_ = request;
370 pending_active_match_ordinal_ = true;
371 return;
372 }
373
374 // This is an initial find operation.
375 Reset(request);
376 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes())
ncarter (slow) 2016/05/31 21:07:31 This iteration may include nodes for which IsRende
paulmeyer 2016/06/01 19:22:06 Oh, I misunderstood. I thought you were suggesting
377 AddFrame(node->current_frame_host());
378 }
379
380 void FindRequestManager::AdvanceQueue(int request_id) {
381 if (find_request_queue_.empty() ||
382 request_id != find_request_queue_.front().id) {
383 return;
384 }
385
386 find_request_queue_.pop();
387 if (!find_request_queue_.empty())
388 FindInternal(find_request_queue_.front());
389 }
390
112 void FindRequestManager::SendFindIPC(const FindRequest& request, 391 void FindRequestManager::SendFindIPC(const FindRequest& request,
113 RenderFrameHost* rfh) { 392 RenderFrameHost* rfh) {
393 pending_replies_.insert(rfh);
114 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id, 394 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id,
115 request.search_text, request.options)); 395 request.search_text, request.options));
116 } 396 }
117 397
118 void FindRequestManager::SendStopFindingIPC(StopFindAction action,
119 RenderFrameHost* rfh) const {
120 rfh->Send(new FrameMsg_StopFinding(rfh->GetRoutingID(), action));
121 }
122
123 void FindRequestManager::NotifyFindReply(int request_id, 398 void FindRequestManager::NotifyFindReply(int request_id,
124 bool final_update) const { 399 bool final_update) const {
125 if (request_id == kInvalidId) { 400 if (request_id == kInvalidId) {
126 NOTREACHED(); 401 NOTREACHED();
127 return; 402 return;
128 } 403 }
129 404
130 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_, 405 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_,
131 active_match_ordinal_, final_update); 406 active_match_ordinal_, final_update);
132 } 407 }
133 408
409 RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const {
410 RenderFrameHost* rfh = contents_->GetMainFrame();
411
412 if (!forward)
413 rfh = GetDeepestLastChild(rfh);
414
415 return rfh;
416 }
417
418 RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* rfh,
419 bool forward,
420 bool matches_only,
421 bool wrap) const {
422 FrameTreeNode* node =
423 static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
424
425 while ((node = TraverseNode(node, forward, wrap)) != nullptr) {
426 if (!CheckFrame(node->current_frame_host()))
427 continue;
428 RenderFrameHost* current_rfh = node->current_frame_host();
429 if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
430 pending_replies_.count(current_rfh)) {
431 // Note that if there is still a pending reply expected for this frame,
432 // then it may have unaccounted matches and will not be skipped via
433 // |matches_only|.
434 return node->current_frame_host();
435 }
436 if (wrap && node->current_frame_host() == rfh)
437 return nullptr;
438 }
439
440 return nullptr;
441 }
442
443 void FindRequestManager::AddFrame(RenderFrameHost* rfh) {
444 DCHECK(rfh && rfh->IsRenderFrameLive());
445
446 // A frame that is already being searched should not be added again.
447 DCHECK(!CheckFrame(rfh));
448
449 matches_per_frame_[rfh] = 0;
450
451 FindRequest request = current_request_;
452 request.id = current_session_id_;
453 request.options.findNext = false;
454 SendFindIPC(request, rfh);
455 }
456
457 bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
458 return rfh && matches_per_frame_.count(rfh) == 1;
459 }
460
461 void FindRequestManager::UpdateActiveMatchOrdinal() {
462 if (!active_frame_ || relative_active_match_ordinal_ == 0) {
463 active_match_ordinal_ = 0;
464 return;
465 }
466
467 RenderFrameHost* rfh = active_frame_;
468 if (!rfh) {
469 RemoveFrame(active_frame_);
470 active_match_ordinal_ = 0;
471 return;
472 }
473
474 // Traverse the frame tree backwards (in search order) and count all of the
475 // matches in frames before the frame with the active match, in order to
476 // determine the overall active match ordinal.
477 active_match_ordinal_ = 0;
478 while ((rfh = Traverse(rfh,
479 false /* forward */,
480 true /* matches_only */,
481 false /* wrap */)) != nullptr) {
482 active_match_ordinal_ += matches_per_frame_[rfh];
483 }
484 active_match_ordinal_ += relative_active_match_ordinal_;
485 }
486
487 void FindRequestManager::FinalUpdate(int request_id, RenderFrameHost* rfh) {
488 if (!number_of_matches_ ||
489 !pending_active_match_ordinal_ ||
490 request_id != current_request_.id) {
491 NotifyFindReply(request_id, true /* final_update */);
492 AdvanceQueue(request_id);
493 return;
494 }
495
496 // There are matches, but no active match was returned, so another find next
497 // request must be sent.
498
499 RenderFrameHost* target_rfh;
500 if (current_request_.options.findNext) {
501 // If this was a find next operation, then the active match will be in the
502 // next frame with matches after this one.
503 target_rfh = Traverse(rfh,
504 current_request_.options.forward,
505 true /* matches_only */,
506 true /* wrap */);
507 } else if ((target_rfh = contents_->GetFocusedFrame()) != nullptr) {
508 // Otherwise, if there is a focused frame, then the active match will be in
509 // the next frame with matches after that one.
510 target_rfh = Traverse(target_rfh,
511 current_request_.options.forward,
512 true /* matches_only */,
513 true /* wrap */);
514 } else {
515 // Otherwise, the first frame with matches will have the active match.
516 target_rfh = GetInitialFrame(current_request_.options.forward);
517 if (!CheckFrame(target_rfh) || !matches_per_frame_[target_rfh]) {
518 target_rfh = Traverse(target_rfh,
519 current_request_.options.forward,
520 true /* matches_only */,
521 false /* wrap */);
522 }
523 }
524 DCHECK(target_rfh);
525
526 // Forward the find reply without |final_update| set because the active match
527 // has not yet been found.
528 NotifyFindReply(request_id, false /* final_update */);
529
530 current_request_.options.findNext = true;
531 SendFindIPC(current_request_, target_rfh);
532 }
533
134 #if defined(OS_ANDROID) 534 #if defined(OS_ANDROID)
135 void FindRequestManager::SendFindMatchRectsIPC(RenderFrameHost* rfh) { 535 void FindRequestManager::RemoveNearestFindResultPendingReply(
136 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), 536 RenderFrameHost* rfh) {
137 match_rects_.request_version)); 537 auto it = activate_.pending_replies.find(rfh);
538 if (it == activate_.pending_replies.end())
539 return;
540
541 activate_.pending_replies.erase(it);
542 if (activate_.pending_replies.empty() &&
543 CheckFrame(activate_.nearest_frame)) {
544 activate_.nearest_frame->Send(new FrameMsg_ActivateNearestFindResult(
545 activate_.nearest_frame->GetRoutingID(),
546 current_session_id_, activate_.x, activate_.y));
547 }
548 }
549
550 void FindRequestManager::RemoveFindMatchRectsPendingReply(
551 RenderFrameHost* rfh) {
552 auto it = match_rects_.pending_replies.find(rfh);
553 if (it == match_rects_.pending_replies.end())
554 return;
555
556 match_rects_.pending_replies.erase(it);
557 if (match_rects_.pending_replies.empty()) {
558 // All replies are in.
559 std::vector<gfx::RectF> aggregate_rects;
560 if (match_rects_.request_version != match_rects_.known_version) {
561 // Request version is stale, so aggregate and report the newer find
562 // match rects. The rects should be aggregated in search order.
563 for (RenderFrameHost* frame = GetInitialFrame(true /* forward */); frame;
564 frame = Traverse(frame,
565 true /* forward */,
566 true /* matches_only */,
567 false /* wrap */)) {
568 auto it = match_rects_.frame_rects.find(frame);
569 if (it == match_rects_.frame_rects.end())
570 continue;
571
572 std::vector<gfx::RectF>& frame_rects = it->second.rects;
573 aggregate_rects.insert(
574 aggregate_rects.end(), frame_rects.begin(), frame_rects.end());
575 }
576 }
577 contents_->NotifyFindMatchRectsReply(
578 match_rects_.known_version, aggregate_rects, match_rects_.active_rect);
579 }
138 } 580 }
139 #endif 581 #endif
140 582
141 } // namespace content 583 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/find_request_manager.h ('k') | content/browser/find_request_manager_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698