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

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

Powered by Google App Engine
This is Rietveld 408576698