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

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

Issue 2249133002: Changes to how FindRequestManager reports find results. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Expanded comment for FinalUpdate(), and renamed to FinalUpdateReceived(). Created 4 years, 3 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
« no previous file with comments | « content/browser/find_request_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 FindRequestManager::FindMatchRectsState::~FindMatchRectsState() {} 84 FindRequestManager::FindMatchRectsState::~FindMatchRectsState() {}
85 #endif 85 #endif
86 86
87 // static 87 // static
88 const int FindRequestManager::kInvalidId = -1; 88 const int FindRequestManager::kInvalidId = -1;
89 89
90 FindRequestManager::FindRequestManager(WebContentsImpl* web_contents) 90 FindRequestManager::FindRequestManager(WebContentsImpl* web_contents)
91 : WebContentsObserver(web_contents), 91 : WebContentsObserver(web_contents),
92 contents_(web_contents), 92 contents_(web_contents),
93 current_session_id_(kInvalidId), 93 current_session_id_(kInvalidId),
94 pending_find_next_reply_(nullptr),
94 pending_active_match_ordinal_(false), 95 pending_active_match_ordinal_(false),
95 number_of_matches_(0), 96 number_of_matches_(0),
96 active_frame_(nullptr), 97 active_frame_(nullptr),
97 relative_active_match_ordinal_(0), 98 relative_active_match_ordinal_(0),
98 active_match_ordinal_(0) {} 99 active_match_ordinal_(0),
100 last_reported_id_(kInvalidId) {}
99 101
100 FindRequestManager::~FindRequestManager() {} 102 FindRequestManager::~FindRequestManager() {}
101 103
102 void FindRequestManager::Find(int request_id, 104 void FindRequestManager::Find(int request_id,
103 const base::string16& search_text, 105 const base::string16& search_text,
104 const blink::WebFindOptions& options) { 106 const blink::WebFindOptions& options) {
105 // Every find request must have a unique ID, and these IDs must strictly 107 // Every find request must have a unique ID, and these IDs must strictly
106 // increase so that newer requests always have greater IDs than older 108 // increase so that newer requests always have greater IDs than older
107 // requests. 109 // requests.
108 DCHECK_GT(request_id, current_request_.id); 110 DCHECK_GT(request_id, current_request_.id);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 AdvanceQueue(request_id); 185 AdvanceQueue(request_id);
184 } 186 }
185 187
186 if (!final_update) { 188 if (!final_update) {
187 NotifyFindReply(request_id, false /* final_update */); 189 NotifyFindReply(request_id, false /* final_update */);
188 return; 190 return;
189 } 191 }
190 192
191 // This is the final update for this frame for the current find operation. 193 // This is the final update for this frame for the current find operation.
192 194
193 pending_replies_.erase(rfh); 195 pending_initial_replies_.erase(rfh);
194 if (request_id == current_session_id_ && !pending_replies_.empty()) { 196 if (request_id == current_session_id_ && !pending_initial_replies_.empty()) {
195 NotifyFindReply(request_id, false /* final_update */); 197 NotifyFindReply(request_id, false /* final_update */);
196 return; 198 return;
197 } 199 }
198 DCHECK(request_id == current_session_id_ ||
199 current_request_.options.findNext);
200 200
201 // This is the final update for the current find operation. 201 // This is the final update for the current find operation.
202 FinalUpdate(request_id, rfh); 202
203 if (request_id == current_request_.id && request_id != current_session_id_) {
204 DCHECK(current_request_.options.findNext);
205 DCHECK_EQ(pending_find_next_reply_, rfh);
206 pending_find_next_reply_ = nullptr;
207 }
208
209 FinalUpdateReceived(request_id, rfh);
203 } 210 }
204 211
205 void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) { 212 void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
206 if (current_session_id_ == kInvalidId || !CheckFrame(rfh)) 213 if (current_session_id_ == kInvalidId || !CheckFrame(rfh))
207 return; 214 return;
208 215
209 // If matches are counted for the frame that is being removed, decrement the 216 // If matches are counted for the frame that is being removed, decrement the
210 // match total before erasing that entry. 217 // match total before erasing that entry.
211 auto it = matches_per_frame_.find(rfh); 218 auto it = matches_per_frame_.find(rfh);
212 if (it != matches_per_frame_.end()) { 219 if (it != matches_per_frame_.end()) {
213 number_of_matches_ -= it->second; 220 number_of_matches_ -= it->second;
214 matches_per_frame_.erase(it); 221 matches_per_frame_.erase(it);
215 } 222 }
216 223
217 // Update the active match ordinal, since it may have changed. 224 // Update the active match ordinal, since it may have changed.
218 if (active_frame_ == rfh) { 225 if (active_frame_ == rfh) {
219 active_frame_ = nullptr; 226 active_frame_ = nullptr;
220 relative_active_match_ordinal_ = 0; 227 relative_active_match_ordinal_ = 0;
228 selection_rect_ = gfx::Rect();
221 } 229 }
222 UpdateActiveMatchOrdinal(); 230 UpdateActiveMatchOrdinal();
223 231
224 #if defined(OS_ANDROID) 232 #if defined(OS_ANDROID)
225 // The removed frame may contain the nearest find result known so far. Note 233 // 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 234 // that once all queried frames have responded, if this result was the overall
227 // nearest, then no activation will occur. 235 // nearest, then no activation will occur.
228 if (rfh == activate_.nearest_frame) 236 if (rfh == activate_.nearest_frame)
229 activate_.nearest_frame = nullptr; 237 activate_.nearest_frame = nullptr;
230 238
231 // Match rects in the removed frame are no longer relevant. 239 // Match rects in the removed frame are no longer relevant.
232 if (match_rects_.frame_rects.count(rfh)) { 240 if (match_rects_.frame_rects.count(rfh)) {
233 match_rects_.frame_rects.erase(rfh); 241 match_rects_.frame_rects.erase(rfh);
234 ++match_rects_.known_version; 242 ++match_rects_.known_version;
235 } 243 }
236 244
237 // A reply should not be expected from the removed frame. 245 // A reply should not be expected from the removed frame.
238 RemoveNearestFindResultPendingReply(rfh); 246 RemoveNearestFindResultPendingReply(rfh);
239 RemoveFindMatchRectsPendingReply(rfh); 247 RemoveFindMatchRectsPendingReply(rfh);
240 #endif 248 #endif
241 249
242 if (pending_replies_.count(rfh)) { 250 // If no pending find replies are expected for the removed frame, then just
251 // report the updated results.
252 if (!pending_initial_replies_.count(rfh) && pending_find_next_reply_ != rfh) {
253 bool final_update =
254 pending_initial_replies_.empty() && !pending_find_next_reply_;
255 NotifyFindReply(current_session_id_, final_update);
256 return;
257 }
258
259 if (pending_initial_replies_.count(rfh)) {
243 // A reply should not be expected from the removed frame. 260 // A reply should not be expected from the removed frame.
244 pending_replies_.erase(rfh); 261 pending_initial_replies_.erase(rfh);
245 if (pending_replies_.empty()) { 262 if (pending_initial_replies_.empty()) {
246 FinalUpdate(current_request_.id, rfh); 263 FinalUpdateReceived(current_session_id_, rfh);
247 return;
248 } 264 }
249 } 265 }
250 266
251 NotifyFindReply(current_session_id_, 267 if (pending_find_next_reply_ == rfh) {
252 pending_replies_.empty() /* final_update */); 268 // A reply should not be expected from the removed frame.
269 pending_find_next_reply_ = nullptr;
270 FinalUpdateReceived(current_request_.id, rfh);
271 }
253 } 272 }
254 273
255 #if defined(OS_ANDROID) 274 #if defined(OS_ANDROID)
256 void FindRequestManager::ActivateNearestFindResult(float x, float y) { 275 void FindRequestManager::ActivateNearestFindResult(float x, float y) {
257 if (current_session_id_ == kInvalidId) 276 if (current_session_id_ == kInvalidId)
258 return; 277 return;
259 278
260 activate_ = ActivateNearestFindResultState(x, y); 279 activate_ = ActivateNearestFindResultState(x, y);
261 280
262 // Request from each frame the distance to the nearest find result (in that 281 // 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. 282 // frame) from the point (x, y), defined in find-in-page coordinates.
264 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) { 283 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
265 RenderFrameHost* rfh = node->current_frame_host(); 284 RenderFrameHost* rfh = node->current_frame_host();
266 285
267 if (!CheckFrame(rfh)) 286 if (!CheckFrame(rfh) || !rfh->IsRenderFrameLive())
268 continue; 287 continue;
269 288
270 activate_.pending_replies.insert(rfh); 289 activate_.pending_replies.insert(rfh);
271 rfh->Send(new FrameMsg_GetNearestFindResult( 290 rfh->Send(new FrameMsg_GetNearestFindResult(
272 rfh->GetRoutingID(), activate_.current_request_id, 291 rfh->GetRoutingID(), activate_.current_request_id,
273 activate_.x, activate_.y)); 292 activate_.x, activate_.y));
274 } 293 }
275 } 294 }
276 295
277 void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh, 296 void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh,
(...skipping 14 matching lines...) Expand all
292 } 311 }
293 312
294 void FindRequestManager::RequestFindMatchRects(int current_version) { 313 void FindRequestManager::RequestFindMatchRects(int current_version) {
295 match_rects_.pending_replies.clear(); 314 match_rects_.pending_replies.clear();
296 match_rects_.request_version = current_version; 315 match_rects_.request_version = current_version;
297 316
298 // Request the latest find match rects from each frame. 317 // Request the latest find match rects from each frame.
299 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) { 318 for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
300 RenderFrameHost* rfh = node->current_frame_host(); 319 RenderFrameHost* rfh = node->current_frame_host();
301 320
302 if (!CheckFrame(rfh)) 321 if (!CheckFrame(rfh) || !rfh->IsRenderFrameLive())
303 continue; 322 continue;
304 323
305 match_rects_.pending_replies.insert(rfh); 324 match_rects_.pending_replies.insert(rfh);
306 auto it = match_rects_.frame_rects.find(rfh); 325 auto it = match_rects_.frame_rects.find(rfh);
307 int version = (it != match_rects_.frame_rects.end()) 326 int version = (it != match_rects_.frame_rects.end())
308 ? it->second.version : kInvalidId; 327 ? it->second.version : kInvalidId;
309 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version)); 328 rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version));
310 } 329 }
311 } 330 }
312 331
(...skipping 23 matching lines...) Expand all
336 RemoveFrame(old_host); 355 RemoveFrame(old_host);
337 } 356 }
338 357
339 void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) { 358 void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) {
340 RemoveFrame(rfh); 359 RemoveFrame(rfh);
341 } 360 }
342 361
343 void FindRequestManager::Reset(const FindRequest& initial_request) { 362 void FindRequestManager::Reset(const FindRequest& initial_request) {
344 current_session_id_ = initial_request.id; 363 current_session_id_ = initial_request.id;
345 current_request_ = initial_request; 364 current_request_ = initial_request;
346 pending_replies_.clear(); 365 pending_initial_replies_.clear();
366 pending_find_next_reply_ = nullptr;
347 pending_active_match_ordinal_ = true; 367 pending_active_match_ordinal_ = true;
348 matches_per_frame_.clear(); 368 matches_per_frame_.clear();
349 number_of_matches_ = 0; 369 number_of_matches_ = 0;
350 active_frame_ = nullptr; 370 active_frame_ = nullptr;
351 relative_active_match_ordinal_ = 0; 371 relative_active_match_ordinal_ = 0;
352 active_match_ordinal_ = 0; 372 active_match_ordinal_ = 0;
353 selection_rect_ = gfx::Rect(); 373 selection_rect_ = gfx::Rect();
374 last_reported_id_ = kInvalidId;
354 #if defined(OS_ANDROID) 375 #if defined(OS_ANDROID)
355 activate_ = ActivateNearestFindResultState(); 376 activate_ = ActivateNearestFindResultState();
356 match_rects_.pending_replies.clear(); 377 match_rects_.pending_replies.clear();
357 #endif 378 #endif
358 } 379 }
359 380
360 void FindRequestManager::FindInternal(const FindRequest& request) { 381 void FindRequestManager::FindInternal(const FindRequest& request) {
361 DCHECK_GT(request.id, current_request_.id); 382 DCHECK_GT(request.id, current_request_.id);
362 DCHECK_GT(request.id, current_session_id_); 383 DCHECK_GT(request.id, current_session_id_);
363 384
(...skipping 29 matching lines...) Expand all
393 return; 414 return;
394 } 415 }
395 416
396 find_request_queue_.pop(); 417 find_request_queue_.pop();
397 if (!find_request_queue_.empty()) 418 if (!find_request_queue_.empty())
398 FindInternal(find_request_queue_.front()); 419 FindInternal(find_request_queue_.front());
399 } 420 }
400 421
401 void FindRequestManager::SendFindIPC(const FindRequest& request, 422 void FindRequestManager::SendFindIPC(const FindRequest& request,
402 RenderFrameHost* rfh) { 423 RenderFrameHost* rfh) {
403 pending_replies_.insert(rfh); 424 DCHECK(CheckFrame(rfh));
425 DCHECK(rfh->IsRenderFrameLive());
426
427 if (request.options.findNext)
428 pending_find_next_reply_ = rfh;
429 else
430 pending_initial_replies_.insert(rfh);
431
404 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id, 432 rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id,
405 request.search_text, request.options)); 433 request.search_text, request.options));
406 } 434 }
407 435
408 void FindRequestManager::NotifyFindReply(int request_id, 436 void FindRequestManager::NotifyFindReply(int request_id, bool final_update) {
409 bool final_update) const {
410 if (request_id == kInvalidId) { 437 if (request_id == kInvalidId) {
411 NOTREACHED(); 438 NOTREACHED();
412 return; 439 return;
413 } 440 }
414 441
442 // Ensure that replies are not reported with IDs lower than the ID of the
443 // latest request we have results from.
444 if (request_id < last_reported_id_)
445 request_id = last_reported_id_;
446 else
447 last_reported_id_ = request_id;
448
415 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_, 449 contents_->NotifyFindReply(request_id, number_of_matches_, selection_rect_,
416 active_match_ordinal_, final_update); 450 active_match_ordinal_, final_update);
417 } 451 }
418 452
419 RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const { 453 RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const {
420 RenderFrameHost* rfh = contents_->GetMainFrame(); 454 RenderFrameHost* rfh = contents_->GetMainFrame();
421 455
422 if (!forward) 456 if (!forward)
423 rfh = GetDeepestLastChild(rfh); 457 rfh = GetDeepestLastChild(rfh);
424 458
425 return rfh; 459 return rfh;
426 } 460 }
427 461
428 RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* from_rfh, 462 RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* from_rfh,
429 bool forward, 463 bool forward,
430 bool matches_only, 464 bool matches_only,
431 bool wrap) const { 465 bool wrap) const {
432 FrameTreeNode* node = 466 FrameTreeNode* node =
433 static_cast<RenderFrameHostImpl*>(from_rfh)->frame_tree_node(); 467 static_cast<RenderFrameHostImpl*>(from_rfh)->frame_tree_node();
434 468
435 while ((node = TraverseNode(node, forward, wrap)) != nullptr) { 469 while ((node = TraverseNode(node, forward, wrap)) != nullptr) {
436 if (!CheckFrame(node->current_frame_host())) 470 if (!CheckFrame(node->current_frame_host()))
437 continue; 471 continue;
438 RenderFrameHost* current_rfh = node->current_frame_host(); 472 RenderFrameHost* current_rfh = node->current_frame_host();
439 if (!matches_only || matches_per_frame_.find(current_rfh)->second || 473 if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
440 pending_replies_.count(current_rfh)) { 474 pending_initial_replies_.count(current_rfh)) {
441 // Note that if there is still a pending reply expected for this frame, 475 // 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 476 // then it may have unaccounted matches and will not be skipped via
443 // |matches_only|. 477 // |matches_only|.
444 return node->current_frame_host(); 478 return node->current_frame_host();
445 } 479 }
446 if (wrap && node->current_frame_host() == from_rfh) 480 if (wrap && node->current_frame_host() == from_rfh)
447 return nullptr; 481 return nullptr;
448 } 482 }
449 483
450 return nullptr; 484 return nullptr;
451 } 485 }
452 486
453 void FindRequestManager::AddFrame(RenderFrameHost* rfh) { 487 void FindRequestManager::AddFrame(RenderFrameHost* rfh) {
454 if (!rfh || !rfh->IsRenderFrameLive()) 488 if (!rfh || !rfh->IsRenderFrameLive())
455 return; 489 return;
456 490
457 // A frame that is already being searched should not be added again. 491 // A frame that is already being searched should not be added again.
458 DCHECK(!CheckFrame(rfh)); 492 DCHECK(!CheckFrame(rfh));
459 493
460 matches_per_frame_[rfh] = 0; 494 matches_per_frame_[rfh] = 0;
461 495
462 FindRequest request = current_request_; 496 FindRequest request = current_request_;
463 request.id = current_session_id_; 497 request.id = current_session_id_;
464 request.options.findNext = false; 498 request.options.findNext = false;
465 SendFindIPC(request, rfh); 499 SendFindIPC(request, rfh);
466 } 500 }
467 501
468 bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const { 502 bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
469 return rfh && rfh->IsRenderFrameLive() && matches_per_frame_.count(rfh); 503 return rfh && matches_per_frame_.count(rfh);
470 } 504 }
471 505
472 void FindRequestManager::UpdateActiveMatchOrdinal() { 506 void FindRequestManager::UpdateActiveMatchOrdinal() {
473 active_match_ordinal_ = 0; 507 active_match_ordinal_ = 0;
474 508
475 if (!active_frame_ || !relative_active_match_ordinal_) { 509 if (!active_frame_ || !relative_active_match_ordinal_) {
476 DCHECK(!active_frame_ && !relative_active_match_ordinal_); 510 DCHECK(!active_frame_ && !relative_active_match_ordinal_);
477 return; 511 return;
478 } 512 }
479 513
480 // Traverse the frame tree backwards (in search order) and count all of the 514 // 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 515 // matches in frames before the frame with the active match, in order to
482 // determine the overall active match ordinal. 516 // determine the overall active match ordinal.
483 RenderFrameHost* frame = active_frame_; 517 RenderFrameHost* frame = active_frame_;
484 while ((frame = Traverse(frame, 518 while ((frame = Traverse(frame,
485 false /* forward */, 519 false /* forward */,
486 true /* matches_only */, 520 true /* matches_only */,
487 false /* wrap */)) != nullptr) { 521 false /* wrap */)) != nullptr) {
488 active_match_ordinal_ += matches_per_frame_[frame]; 522 active_match_ordinal_ += matches_per_frame_[frame];
489 } 523 }
490 active_match_ordinal_ += relative_active_match_ordinal_; 524 active_match_ordinal_ += relative_active_match_ordinal_;
491 } 525 }
492 526
493 void FindRequestManager::FinalUpdate(int request_id, RenderFrameHost* rfh) { 527 void FindRequestManager::FinalUpdateReceived(int request_id,
528 RenderFrameHost* rfh) {
494 if (!number_of_matches_ || 529 if (!number_of_matches_ ||
495 !pending_active_match_ordinal_ || 530 (active_match_ordinal_ && !pending_active_match_ordinal_) ||
496 request_id != current_request_.id) { 531 request_id != current_request_.id) {
497 NotifyFindReply(request_id, true /* final_update */); 532 // All the find results for |request_id| are in and ready to report. Note
533 // that |final_update| will be set to false if there are still pending
534 // replies expected from the initial find request.
535 NotifyFindReply(request_id,
536 pending_initial_replies_.empty() /* final_update */);
498 AdvanceQueue(request_id); 537 AdvanceQueue(request_id);
499 return; 538 return;
500 } 539 }
501 540
502 // There are matches, but no active match was returned, so another find next 541 // There are matches, but no active match was returned, so another find next
503 // request must be sent. 542 // request must be sent.
504 543
505 RenderFrameHost* target_rfh; 544 RenderFrameHost* target_rfh;
506 if (current_request_.options.findNext) { 545 if (current_request_.options.findNext) {
507 // If this was a find next operation, then the active match will be in the 546 // If this was a find next operation, then the active match will be in the
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 aggregate_rects.end(), frame_rects.begin(), frame_rects.end()); 619 aggregate_rects.end(), frame_rects.begin(), frame_rects.end());
581 } 620 }
582 } 621 }
583 contents_->NotifyFindMatchRectsReply( 622 contents_->NotifyFindMatchRectsReply(
584 match_rects_.known_version, aggregate_rects, match_rects_.active_rect); 623 match_rects_.known_version, aggregate_rects, match_rects_.active_rect);
585 } 624 }
586 } 625 }
587 #endif 626 #endif
588 627
589 } // namespace content 628 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/find_request_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698