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

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@, and a bit of cleanup. 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) {
dglazkov 2016/06/02 04:48:57 Can this live in some common FrameTreeNode place?
paulmeyer 2016/06/02 17:36:36 Yeah, it can, and I agree that it should. I had a
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.
112 if (!options.findNext)
113 find_request_queue_ = std::queue<FindRequest>();
35 114
36 if (options.findNext) { 115 find_request_queue_.emplace(request_id, search_text, options);
37 // This is a find next operation. 116 if (find_request_queue_.size() == 1)
38 117 FindInternal(find_request_queue_.front());
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 }
49
50 SendFindIPC(request, contents_->GetMainFrame());
51 } 118 }
52 119
53 void FindRequestManager::StopFinding(StopFindAction action) { 120 void FindRequestManager::StopFinding(StopFindAction action) {
54 SendStopFindingIPC(action, contents_->GetMainFrame()); 121 contents_->SendToAllFrames(
122 new FrameMsg_StopFinding(MSG_ROUTING_NONE, action));
123
55 current_session_id_ = kInvalidId; 124 current_session_id_ = kInvalidId;
125 #if defined(OS_ANDROID)
126 // It is important that these pending replies are cleared whenever a find
127 // session ends, so that subsequent replies for the old session are ignored.
128 activate_.pending_replies.clear();
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 matches are counted for the frame that is being removed, decrement the
210 // match total before erasing that entry.
211 auto it = matches_per_frame_.find(rfh);
212 if (it != matches_per_frame_.end()) {
213 number_of_matches_ -= it->second;
214 matches_per_frame_.erase(it);
215 }
216
217 // Update the active match ordinal, since it may have changed.
218 if (active_frame_ == rfh) {
219 active_frame_ = nullptr;
220 relative_active_match_ordinal_ = 0;
221 }
222 UpdateActiveMatchOrdinal();
223
224 #if defined(OS_ANDROID)
225 // The removed frame may contain the nearest find result known so far. Note
226 // that once all queried frames have responded, if this result was the overall
227 // nearest, then no activation will occur.
228 if (rfh == activate_.nearest_frame)
229 activate_.nearest_frame = nullptr;
230
231 // Match rects in the removed frame are no longer relevant.
232 if (match_rects_.count(rfh)) {
233 match_rects_.frame_rects.erase(rfh);
234 ++match_rects_.known_version;
235 }
236
237 // A reply should not be expected from the removed frame.
238 RemoveNearestFindResultPendingReply(rfh);
239 RemoveFindMatchRectsPendingReply(rfh);
240 #endif
241
242 if (pending_replies_.count(rfh)) {
243 // A reply should not be expected from the removed frame.
244 pending_replies_.erase(rfh);
245 if (pending_replies_.empty()) {
246 FinalUpdate(current_request_.id, rfh);
247 return;
248 }
249 }
250
251 NotifyFindReply(current_session_id_,
252 pending_replies_.empty() /* final_update */);
74 } 253 }
75 254
76 #if defined(OS_ANDROID) 255 #if defined(OS_ANDROID)
77 void FindRequestManager::ActivateNearestFindResult(float x, 256 void FindRequestManager::ActivateNearestFindResult(float x, float y) {
78 float y) {
79 if (current_session_id_ == kInvalidId) 257 if (current_session_id_ == kInvalidId)
80 return; 258 return;
81 259
82 auto rfh = contents_->GetMainFrame(); 260 activate_ = ActivateNearestFindResultState(x, y);
83 rfh->Send(new InputMsg_ActivateNearestFindResult( 261
84 rfh->GetRoutingID(), current_session_id_, x, y)); 262 // Request from each frame the distance to the nearest find result (in that
263 // frame) from the point (x, y), defined in find-in-page coordinates.
264 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
265 RenderFrameHost* rfh = node->current_frame_host();
266
267 if (!CheckFrame(rfh))
268 continue;
269
270 activate_.pending_replies.insert(rfh);
271 rfh->Send(new FrameMsg_GetNearestFindResult(
272 rfh->GetRoutingID(), activate_.current_request_id,
273 activate_.x, activate_.y));
274 }
275 }
276
277 void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh,
278 int request_id,
279 float distance) {
280 if (request_id != activate_.current_request_id ||
281 !activate_.pending_replies.count(rfh)) {
282 return;
283 }
284
285 // Check if this frame has a nearer find result than the current nearest.
286 if (distance < activate_.nearest_distance) {
287 activate_.nearest_frame = rfh;
288 activate_.nearest_distance = distance;
289 }
290
291 RemoveNearestFindResultPendingReply(rfh);
85 } 292 }
86 293
87 void FindRequestManager::RequestFindMatchRects(int current_version) { 294 void FindRequestManager::RequestFindMatchRects(int current_version) {
295 match_rects_.pending_replies.clear();
88 match_rects_.request_version = current_version; 296 match_rects_.request_version = current_version;
89 SendFindMatchRectsIPC(contents_->GetMainFrame()); 297
298 // Request the latest find match rects from each frame.
299 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
300 RenderFrameHost* rfh = node->current_frame_host();
301
302 if (!CheckFrame(rfh))
303 continue;
304
305 match_rects_.pending_replies.insert(rfh);
306 auto it = match_rects_.frame_rects.find(rfh);
307 int version = (it != match_rects_.frame_rects.end())
308 ? it->second.version : kInvalidId;
309 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version));
310 }
90 } 311 }
91 312
92 void FindRequestManager::OnFindMatchRectsReply( 313 void FindRequestManager::OnFindMatchRectsReply(
93 RenderFrameHost* rfh, 314 RenderFrameHost* rfh,
94 int version, 315 int version,
95 const std::vector<gfx::RectF>& rects, 316 const std::vector<gfx::RectF>& rects,
96 const gfx::RectF& active_rect) { 317 const gfx::RectF& active_rect) {
97 contents_->NotifyFindMatchRectsReply(version, rects, active_rect); 318 auto it = match_rects_.frame_rects.find(rfh);
319 if (it == match_rects_.frame_rects.end() || it->second.version != version) {
320 // New version of rects has been received, so update the data.
321 match_rects_.frame_rects[rfh] = FrameRects(rects, version);
322 ++match_rects_.known_version;
323 }
324 if (!active_rect.IsEmpty())
325 match_rects_.active_rect = active_rect;
326 RemoveFindMatchRectsPendingReply(rfh);
98 } 327 }
99 #endif 328 #endif
100 329
330 void FindRequestManager::RenderFrameDeleted(RenderFrameHost* rfh) {
331 RemoveFrame(rfh);
332 }
333
334 void FindRequestManager::RenderFrameHostChanged(RenderFrameHost* old_host,
335 RenderFrameHost* new_host) {
336 RemoveFrame(old_host);
337 }
338
339 void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) {
340 RemoveFrame(rfh);
341 }
342
101 void FindRequestManager::Reset(const FindRequest& initial_request) { 343 void FindRequestManager::Reset(const FindRequest& initial_request) {
102 current_session_id_ = initial_request.id; 344 current_session_id_ = initial_request.id;
103 current_request_ = initial_request; 345 current_request_ = initial_request;
346 pending_replies_.clear();
347 pending_active_match_ordinal_ = true;
348 matches_per_frame_.clear();
104 number_of_matches_ = 0; 349 number_of_matches_ = 0;
350 active_frame_ = nullptr;
351 relative_active_match_ordinal_ = 0;
105 active_match_ordinal_ = 0; 352 active_match_ordinal_ = 0;
106 selection_rect_ = gfx::Rect(); 353 selection_rect_ = gfx::Rect();
107 #if defined(OS_ANDROID) 354 #if defined(OS_ANDROID)
108 match_rects_ = FindMatchRectsState(); 355 activate_ = ActivateNearestFindResultState();
356 match_rects_.pending_replies.clear();
109 #endif 357 #endif
110 } 358 }
111 359
360 void FindRequestManager::FindInternal(const FindRequest& request) {
361 DCHECK_GT(request.id, current_request_.id);
362 DCHECK_GT(request.id, current_session_id_);
363
364 if (request.options.findNext) {
365 // This is a find next operation.
366
367 // This implies that there is an ongoing find session with the same search
368 // text.
369 DCHECK_GE(current_session_id_, 0);
370 DCHECK_EQ(request.search_text, current_request_.search_text);
371
372 // The find next request will be directed at the focused frame if there is
373 // one, or the first frame with matches otherwise.
374 RenderFrameHost* target_rfh = contents_->GetFocusedFrame();
375 if (!target_rfh || !CheckFrame(target_rfh))
376 target_rfh = GetInitialFrame(request.options.forward);
377
378 SendFindIPC(request, target_rfh);
379 current_request_ = request;
380 pending_active_match_ordinal_ = true;
381 return;
382 }
383
384 // This is an initial find operation.
385 Reset(request);
386 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes())
387 AddFrame(node->current_frame_host());
388 }
389
390 void FindRequestManager::AdvanceQueue(int request_id) {
391 if (find_request_queue_.empty() ||
392 request_id != find_request_queue_.front().id) {
393 return;
394 }
395
396 find_request_queue_.pop();
397 if (!find_request_queue_.empty())
398 FindInternal(find_request_queue_.front());
399 }
400
112 void FindRequestManager::SendFindIPC(const FindRequest& request, 401 void FindRequestManager::SendFindIPC(const FindRequest& request,
113 RenderFrameHost* rfh) { 402 RenderFrameHost* rfh) {
403 pending_replies_.insert(rfh);
114 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id, 404 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id,
115 request.search_text, request.options)); 405 request.search_text, request.options));
116 } 406 }
117 407
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, 408 void FindRequestManager::NotifyFindReply(int request_id,
124 bool final_update) const { 409 bool final_update) const {
125 if (request_id == kInvalidId) { 410 if (request_id == kInvalidId) {
126 NOTREACHED(); 411 NOTREACHED();
127 return; 412 return;
128 } 413 }
129 414
130 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_, 415 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_,
131 active_match_ordinal_, final_update); 416 active_match_ordinal_, final_update);
132 } 417 }
133 418
419 RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const {
420 RenderFrameHost* rfh = contents_->GetMainFrame();
421
422 if (!forward)
423 rfh = GetDeepestLastChild(rfh);
424
425 return rfh;
426 }
427
428 RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* from_rfh,
429 bool forward,
430 bool matches_only,
431 bool wrap) const {
432 FrameTreeNode* node =
433 static_cast<RenderFrameHostImpl*>(from_rfh)->frame_tree_node();
434
435 while ((node = TraverseNode(node, forward, wrap)) != nullptr) {
436 if (!CheckFrame(node->current_frame_host()))
437 continue;
438 RenderFrameHost* current_rfh = node->current_frame_host();
439 if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
440 pending_replies_.count(current_rfh)) {
441 // Note that if there is still a pending reply expected for this frame,
442 // then it may have unaccounted matches and will not be skipped via
443 // |matches_only|.
444 return node->current_frame_host();
445 }
446 if (wrap && node->current_frame_host() == from_rfh)
447 return nullptr;
448 }
449
450 return nullptr;
451 }
452
453 void FindRequestManager::AddFrame(RenderFrameHost* rfh) {
454 if (!rfh || !rfh->IsRenderFrameLive())
455 return;
456
457 // A frame that is already being searched should not be added again.
458 DCHECK(!CheckFrame(rfh));
459
460 matches_per_frame_[rfh] = 0;
461
462 FindRequest request = current_request_;
463 request.id = current_session_id_;
464 request.options.findNext = false;
465 SendFindIPC(request, rfh);
466 }
467
468 bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
469 return rfh && rfh->IsRenderFrameLive() && matches_per_frame_.count(rfh);
470 }
471
472 void FindRequestManager::UpdateActiveMatchOrdinal() {
473 active_match_ordinal_ = 0;
474
475 if (!active_frame_ || !relative_active_match_ordinal_) {
476 DCHECK(!active_frame_ && !relative_active_match_ordinal_);
477 return;
478 }
479
480 // Traverse the frame tree backwards (in search order) and count all of the
481 // matches in frames before the frame with the active match, in order to
482 // determine the overall active match ordinal.
483 RenderFrameHost* frame = active_frame_;
484 while ((frame = Traverse(frame,
485 false /* forward */,
486 true /* matches_only */,
487 false /* wrap */))) {
488 active_match_ordinal_ += matches_per_frame_[frame];
489 }
490 active_match_ordinal_ += relative_active_match_ordinal_;
491 }
492
493 void FindRequestManager::FinalUpdate(int request_id, RenderFrameHost* rfh) {
494 if (!number_of_matches_ ||
495 !pending_active_match_ordinal_ ||
496 request_id != current_request_.id) {
497 NotifyFindReply(request_id, true /* final_update */);
498 AdvanceQueue(request_id);
499 return;
500 }
501
502 // There are matches, but no active match was returned, so another find next
503 // request must be sent.
504
505 RenderFrameHost* target_rfh;
506 if (current_request_.options.findNext) {
507 // If this was a find next operation, then the active match will be in the
508 // next frame with matches after this one.
509 target_rfh = Traverse(rfh,
510 current_request_.options.forward,
511 true /* matches_only */,
512 true /* wrap */);
513 } else if ((target_rfh = contents_->GetFocusedFrame()) != nullptr) {
514 // Otherwise, if there is a focused frame, then the active match will be in
515 // the next frame with matches after that one.
516 target_rfh = Traverse(target_rfh,
517 current_request_.options.forward,
518 true /* matches_only */,
519 true /* wrap */);
520 } else {
521 // Otherwise, the first frame with matches will have the active match.
522 target_rfh = GetInitialFrame(current_request_.options.forward);
523 if (!CheckFrame(target_rfh) || !matches_per_frame_[target_rfh]) {
524 target_rfh = Traverse(target_rfh,
525 current_request_.options.forward,
526 true /* matches_only */,
527 false /* wrap */);
528 }
529 }
530 DCHECK(target_rfh);
531
532 // Forward the find reply without |final_update| set because the active match
533 // has not yet been found.
534 NotifyFindReply(request_id, false /* final_update */);
535
536 current_request_.options.findNext = true;
537 SendFindIPC(current_request_, target_rfh);
538 }
539
134 #if defined(OS_ANDROID) 540 #if defined(OS_ANDROID)
135 void FindRequestManager::SendFindMatchRectsIPC(RenderFrameHost* rfh) { 541 void FindRequestManager::RemoveNearestFindResultPendingReply(
136 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), 542 RenderFrameHost* rfh) {
137 match_rects_.request_version)); 543 auto it = activate_.pending_replies.find(rfh);
544 if (it == activate_.pending_replies.end())
545 return;
546
547 activate_.pending_replies.erase(it);
548 if (activate_.pending_replies.empty() &&
549 CheckFrame(activate_.nearest_frame)) {
550 activate_.nearest_frame->Send(new FrameMsg_ActivateNearestFindResult(
551 activate_.nearest_frame->GetRoutingID(),
552 current_session_id_, activate_.x, activate_.y));
553 }
554 }
555
556 void FindRequestManager::RemoveFindMatchRectsPendingReply(
557 RenderFrameHost* rfh) {
558 auto it = match_rects_.pending_replies.find(rfh);
559 if (it == match_rects_.pending_replies.end())
560 return;
561
562 match_rects_.pending_replies.erase(it);
563 if (match_rects_.pending_replies.empty()) {
564 // All replies are in.
565 std::vector<gfx::RectF> aggregate_rects;
566 if (match_rects_.request_version != match_rects_.known_version) {
567 // Request version is stale, so aggregate and report the newer find
568 // match rects. The rects should be aggregated in search order.
569 for (RenderFrameHost* frame = GetInitialFrame(true /* forward */); frame;
570 frame = Traverse(frame,
571 true /* forward */,
572 true /* matches_only */,
573 false /* wrap */)) {
574 auto it = match_rects_.frame_rects.find(frame);
575 if (it == match_rects_.frame_rects.end())
576 continue;
577
578 std::vector<gfx::RectF>& frame_rects = it->second.rects;
579 aggregate_rects.insert(
580 aggregate_rects.end(), frame_rects.begin(), frame_rects.end());
581 }
582 }
583 contents_->NotifyFindMatchRectsReply(
584 match_rects_.known_version, aggregate_rects, match_rects_.active_rect);
585 }
138 } 586 }
139 #endif 587 #endif
140 588
141 } // namespace content 589 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698