Chromium Code Reviews| Index: content/browser/find_request_manager.cc |
| diff --git a/content/browser/find_request_manager.cc b/content/browser/find_request_manager.cc |
| index 915ecf8d9fd51fead4daa96df981924bbf1d753a..43103b54dae23fb4058fe6badaed14fcadbd7587 100644 |
| --- a/content/browser/find_request_manager.cc |
| +++ b/content/browser/find_request_manager.cc |
| @@ -11,13 +11,85 @@ |
| namespace content { |
| +namespace { |
| + |
| +// Returns the key for the frame associated with |rfh|. |
| +FindRequestManager::FrameKey GetFrameKey(RenderFrameHost* rfh) { |
| + return std::make_pair(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); |
| +} |
| + |
| +// Returns the RenderFrameHostImpl associated with |frame_key|. |
| +RenderFrameHostImpl* GetRenderFrameHost( |
| + const FindRequestManager::FrameKey& frame_key) { |
| + return RenderFrameHostImpl::FromID(frame_key.first, frame_key.second); |
| +} |
| + |
| +// Returns the deepest last child frame under |node|/|rfh| in the frame tree. |
| +FrameTreeNode* GetDeepestLastChild(FrameTreeNode* node) { |
| + while (node->child_count()) |
| + node = node->child_at(node->child_count() - 1); |
| + return node; |
| +} |
| +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.
|
| + FrameTreeNode* node = |
| + static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node(); |
| + return GetDeepestLastChild(node)->current_frame_host(); |
| +} |
| + |
| +// Returns the FrameTreeNode directly after |node| in the frame tree in search |
| +// order, or nullptr if one does not exist. If |wrap| is set, then wrapping |
| +// between the first and last frames is permitted. Note that this traversal |
| +// follows the same ordering as in blink::FrameTree::traverseNextWithWrap(). |
| +FrameTreeNode* TraverseNext(FrameTreeNode* node, bool wrap) { |
| + if (node->child_count()) |
| + return node->child_at(0); |
| + |
| + FrameTreeNode* sibling = node->NextSibling(); |
| + while (!sibling) { |
| + if (!node->parent()) |
| + return wrap ? node : nullptr; |
| + node = node->parent(); |
| + sibling = node->NextSibling(); |
| + } |
| + return sibling; |
| +} |
| + |
| +// Returns the FrameTreeNode directly before |node| in the frame tree in search |
| +// order, or nullptr if one does not exist. If |wrap| is set, then wrapping |
| +// between the first and last frames is permitted. Note that this traversal |
| +// follows the same ordering as in blink::FrameTree::traversePreviousWithWrap(). |
| +FrameTreeNode* TraversePrevious(FrameTreeNode* node, bool wrap) { |
| + if (FrameTreeNode* previous_sibling = node->PreviousSibling()) |
| + return GetDeepestLastChild(previous_sibling); |
| + if (node->parent()) |
| + return node->parent(); |
| + return wrap ? GetDeepestLastChild(node) : nullptr; |
| +} |
| + |
| +// The same as either TraverseNext() or TraversePrevious() depending on |
| +// |forward|. |
| +FrameTreeNode* TraverseNode(FrameTreeNode* node, bool forward, bool wrap) { |
| + return forward ? TraverseNext(node, wrap) : TraversePrevious(node, wrap); |
| +} |
| + |
| +} // namespace |
| + |
| +#if defined(OS_ANDROID) |
| +FindRequestManager::FindMatchRectsState::FindMatchRectsState() = default; |
| +FindRequestManager::FindMatchRectsState::~FindMatchRectsState() {} |
| +#endif |
| + |
| // static |
| const int FindRequestManager::kInvalidId = -1; |
| FindRequestManager::FindRequestManager(WebContentsImpl* web_contents) |
| - : contents_(web_contents), |
| + : WebContentsObserver(web_contents), |
| + contents_(web_contents), |
| current_session_id_(kInvalidId), |
| + pending_active_match_ordinal_(kInvalidId), |
| number_of_matches_(0), |
| + relative_active_match_ordinal_( |
| + std::make_pair(std::make_pair(kInvalidId, kInvalidId), 0)), |
| active_match_ordinal_(0) {} |
| FindRequestManager::~FindRequestManager() {} |
| @@ -31,28 +103,25 @@ void FindRequestManager::Find(int request_id, |
| DCHECK_GT(request_id, current_request_.id); |
| DCHECK_GT(request_id, current_session_id_); |
| - FindRequest request(request_id, search_text, options); |
| - |
| - if (options.findNext) { |
| - // This is a find next operation. |
| - |
| - // This implies that there is an ongoing find session with the same search |
| - // text. |
| - DCHECK_GE(current_session_id_, 0); |
| - DCHECK_EQ(request.search_text, current_request_.search_text); |
| - |
| - current_request_ = request; |
| - } else { |
| - // This is an initial find operation. |
| - Reset(request); |
| + // If this is a new find session, clear any queued requests from last session. |
| + if (!options.findNext) { |
| + find_request_queue_ = std::queue<FindRequest>(); |
| } |
| - SendFindIPC(request, contents_->GetMainFrame()); |
| + find_request_queue_.emplace(request_id, search_text, options); |
| + if (find_request_queue_.size() == 1) |
| + FindInternal(find_request_queue_.front()); |
| } |
| void FindRequestManager::StopFinding(StopFindAction action) { |
| - SendStopFindingIPC(action, contents_->GetMainFrame()); |
| + contents_->ForEachFrame(base::Bind( |
| + &FindRequestManager::SendStopFindingIPC, base::Unretained(this), action)); |
| current_session_id_ = kInvalidId; |
| +#if defined(OS_ANDROID) |
| + // It is important that these pending replies are cleared whenever a find |
| + // session ends, so that subsequent replies for the old session are ignored. |
| + match_rects_.pending_replies.clear(); |
| +#endif |
| } |
| void FindRequestManager::OnFindReply(RenderFrameHost* rfh, |
| @@ -64,29 +133,155 @@ void FindRequestManager::OnFindReply(RenderFrameHost* rfh, |
| // Ignore stale replies from abandoned find sessions. |
| if (current_session_id_ == kInvalidId || request_id < current_session_id_) |
| return; |
| + 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
|
| + |
| + FrameKey frame_key = GetFrameKey(rfh); |
| // Update the stored results. |
| - number_of_matches_ = number_of_matches; |
| - selection_rect_ = selection_rect; |
| - active_match_ordinal_ = active_match_ordinal; |
| + if (number_of_matches != -1) { |
| + DCHECK_GE(number_of_matches, 0); |
| + // Increment the global number of matches by the number of additional |
| + // matches found for this frame. |
| + auto matches_per_frame_it = matches_per_frame_.find(frame_key); |
| + number_of_matches_ += number_of_matches - matches_per_frame_it->second; |
| + matches_per_frame_it->second = number_of_matches; |
| + } |
| + if (!selection_rect.IsEmpty()) { |
|
lfg
2016/05/13 20:15:40
nit: no need for {}
paulmeyer
2016/05/16 15:25:11
Done.
|
| + selection_rect_ = selection_rect; |
| + } |
| + if (active_match_ordinal > 0) { |
| + if (GetFrameKey(rfh) == relative_active_match_ordinal_.first) { |
| + active_match_ordinal_ += |
| + active_match_ordinal - relative_active_match_ordinal_.second; |
| + relative_active_match_ordinal_.second = active_match_ordinal; |
| + } else { |
| + if (relative_active_match_ordinal_.first.first != kInvalidId) { |
| + RenderFrameHost* old_rfh = |
| + GetRenderFrameHost(relative_active_match_ordinal_.first); |
| + if (old_rfh && old_rfh != rfh) { |
| + old_rfh->Send(new FrameMsg_ClearActiveFindMatch( |
| + old_rfh->GetRoutingID())); |
| + } |
| + } |
| + relative_active_match_ordinal_ = |
| + std::make_pair(GetFrameKey(rfh), active_match_ordinal); |
| + UpdateActiveMatchOrdinal(); |
| + } |
| + if (pending_active_match_ordinal_ == request_id) |
| + pending_active_match_ordinal_ = kInvalidId; |
| + AdvanceQueue(request_id); |
| + } |
| - NotifyFindReply(request_id, final_update); |
| + if (!final_update) { |
| + NotifyFindReply(request_id, false /* final_update */); |
| + return; |
| + } |
| + |
| + // This is the final update for this frame for the current find operation. |
| + |
| + pending_replies_.erase(frame_key); |
| + if (request_id == current_session_id_ && !pending_replies_.empty()) { |
| + NotifyFindReply(request_id, false /* final_update */); |
| + return; |
| + } |
| + DCHECK(request_id == current_session_id_ || |
| + current_request_.options.findNext); |
| + |
| + // This is the final update for the current find operation. |
| + FinalUpdate(request_id, rfh); |
| +} |
| + |
| +void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) { |
| + RemoveFrame(GetFrameKey(rfh)); |
| +} |
| + |
| +void FindRequestManager::RemoveFrame(const FrameKey& frame_key) { |
| + if (current_session_id_ == kInvalidId || !CheckFrame(frame_key)) |
| + return; |
| + |
| + if (pending_replies_.count(frame_key)) { |
| + // A reply should not be expected from the removed frame. |
| + pending_replies_.erase(frame_key); |
| + if (pending_replies_.empty()) { |
| + FinalUpdate(current_session_id_, GetRenderFrameHost(frame_key)); |
|
lfg
2016/05/13 20:15:40
nit: {}
paulmeyer
2016/05/16 15:25:11
Done.
|
| + } |
| + } |
| + |
| +#if defined(OS_ANDROID) |
| + // A reply should not be expected from the removed frame. |
| + RemoveNearestFindResultPendingReply(frame_key); |
| + RemoveFindMatchRectsPendingReply(frame_key); |
| + |
| + // Match rects in the removed frame are no longer relevant. |
| + match_rects_.rects.erase(frame_key); |
| +#endif |
| + |
| + // If matches are counted for the frame that is being removed, decrement the |
| + // match total before erasing that entry. |
| + auto it = matches_per_frame_.find(frame_key); |
| + if (it != matches_per_frame_.end()) { |
| + number_of_matches_ -= it->second; |
| + matches_per_frame_.erase(it); |
| + } |
| + |
| + // Update the active match ordinal, since it may have changed. |
| + if (relative_active_match_ordinal_.first == frame_key) { |
| + relative_active_match_ordinal_ = |
| + std::make_pair(std::make_pair(kInvalidId, kInvalidId), 0); |
| + } |
| + UpdateActiveMatchOrdinal(); |
| + |
| + NotifyFindReply(current_session_id_, |
| + pending_replies_.empty() /* final_update */); |
| } |
| #if defined(OS_ANDROID) |
| +FindRequestManager::ActivateNearestFindResultState:: |
| +ActivateNearestFindResultState() = default; |
| +FindRequestManager::ActivateNearestFindResultState:: |
| +ActivateNearestFindResultState(float x, float y) |
| + : current_request_id(GetNextID()), |
| + x(x), |
| + y(y) {} |
| +FindRequestManager::ActivateNearestFindResultState:: |
| +~ActivateNearestFindResultState() {}; |
| + |
| void FindRequestManager::ActivateNearestFindResult(float x, |
| float y) { |
| if (current_session_id_ == kInvalidId) |
| return; |
| - auto rfh = contents_->GetMainFrame(); |
| - rfh->Send(new InputMsg_ActivateNearestFindResult( |
| - rfh->GetRoutingID(), current_session_id_, x, y)); |
| + activate_ = ActivateNearestFindResultState(x, y); |
| + |
| + contents_->ForEachFrame(base::Bind( |
| + &FindRequestManager::SendGetNearestFindResultIPC, |
| + base::Unretained(this))); |
| +} |
| + |
| +void FindRequestManager::GetNearestFindResultReply(RenderFrameHost* rfh, |
| + int request_id, |
| + float distance) { |
| + FrameKey frame_key = GetFrameKey(rfh); |
| + |
| + if (request_id != activate_.current_request_id || |
| + !activate_.pending_replies.count(frame_key)) { |
| + return; |
| + } |
| + |
| + // Check if this frame has a nearer find result than the current nearest. |
| + if (distance < activate_.nearest_distance) { |
| + activate_.nearest_frame = frame_key; |
| + activate_.nearest_distance = distance; |
| + } |
| + |
| + RemoveNearestFindResultPendingReply(frame_key); |
| } |
| void FindRequestManager::RequestFindMatchRects(int current_version) { |
| + match_rects_.pending_replies.clear(); |
| match_rects_.request_version = current_version; |
| - SendFindMatchRectsIPC(contents_->GetMainFrame()); |
| + contents_->ForEachFrame(base::Bind( |
| + &FindRequestManager::SendFindMatchRectsIPC, base::Unretained(this))); |
| } |
| void FindRequestManager::OnFindMatchRectsReply( |
| @@ -94,23 +289,88 @@ void FindRequestManager::OnFindMatchRectsReply( |
| int version, |
| const std::vector<gfx::RectF>& rects, |
| const gfx::RectF& active_rect) { |
| - contents_->NotifyFindMatchRectsReply(version, rects, active_rect); |
| + FrameKey frame_key = GetFrameKey(rfh); |
| + auto it = match_rects_.rects.find(frame_key); |
| + if (it == match_rects_.rects.end() || it->second.first != version) { |
| + // New version of rects has been received, so update the data. |
| + match_rects_.rects[frame_key] = std::make_pair(version, rects); |
| + ++match_rects_.known_version; |
| + } |
| + if (!active_rect.IsEmpty()) |
| + match_rects_.active_rect = active_rect; |
| + RemoveFindMatchRectsPendingReply(frame_key); |
| } |
| #endif |
| +void FindRequestManager::RenderFrameDeleted(RenderFrameHost* rfh) { |
| + RemoveFrame(rfh); |
| +} |
| + |
| +void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) { |
| + RemoveFrame(rfh); |
| +} |
| + |
| void FindRequestManager::Reset(const FindRequest& initial_request) { |
| current_session_id_ = initial_request.id; |
| current_request_ = initial_request; |
| + pending_replies_.clear(); |
| + pending_active_match_ordinal_ = initial_request.id; |
| + matches_per_frame_.clear(); |
| number_of_matches_ = 0; |
| + relative_active_match_ordinal_ = |
| + std::make_pair(std::make_pair(kInvalidId, kInvalidId), 0); |
| active_match_ordinal_ = 0; |
| selection_rect_ = gfx::Rect(); |
| #if defined(OS_ANDROID) |
| - match_rects_ = FindMatchRectsState(); |
| + activate_ = ActivateNearestFindResultState(); |
| + match_rects_.pending_replies.clear(); |
| #endif |
| } |
| +void FindRequestManager::FindInternal(const FindRequest& request) { |
| + DCHECK_GT(request.id, current_request_.id); |
| + DCHECK_GT(request.id, current_session_id_); |
| + |
| + if (request.options.findNext) { |
| + // This is a find next operation. |
| + |
| + // This implies that there is an ongoing find session with the same search |
| + // text. |
| + DCHECK_GE(current_session_id_, 0); |
| + DCHECK_EQ(request.search_text, current_request_.search_text); |
| + |
| + // The find next request will be directed at the focused frame if there is |
| + // one, or the first frame with matches otherwise. |
| + RenderFrameHost* target_rfh = contents_->GetFocusedFrame(); |
| + if (!target_rfh || !CheckFrame(target_rfh)) |
| + target_rfh = GetInitialFrame(request.options.forward); |
| + |
| + SendFindIPC(request, target_rfh); |
| + current_request_ = request; |
| + pending_active_match_ordinal_ = request.id; |
| + return; |
| + } |
| + |
| + // This is an initial find operation. |
| + Reset(request); |
| + 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.
|
| + base::Unretained(this))); |
| +} |
| + |
| +void FindRequestManager::AdvanceQueue(int request_id) { |
| + if (find_request_queue_.empty() || |
| + request_id != find_request_queue_.front().id) { |
| + return; |
| + } |
| + |
| + find_request_queue_.pop(); |
| + if (!find_request_queue_.empty()) |
| + FindInternal(find_request_queue_.front()); |
| +} |
| + |
| void FindRequestManager::SendFindIPC(const FindRequest& request, |
| RenderFrameHost* rfh) { |
| + pending_replies_.insert(GetFrameKey(rfh)); |
| rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id, |
| request.search_text, request.options)); |
| } |
| @@ -131,10 +391,195 @@ void FindRequestManager::NotifyFindReply(int request_id, |
| active_match_ordinal_, final_update); |
| } |
| +RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const { |
| + RenderFrameHost* rfh = contents_->GetMainFrame(); |
| + |
| + if (!forward) |
| + rfh = GetDeepestLastChild(rfh); |
| + |
| + return rfh; |
| +} |
| + |
| +RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* rfh, |
| + bool forward, |
| + bool matches_only, |
| + bool wrap) const { |
| + FrameTreeNode* node = |
| + static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node(); |
| + |
| + while ((node = TraverseNode(node, forward, wrap)) != nullptr) { |
| + if (!CheckFrame(node->current_frame_host())) |
| + continue; |
| + FrameKey frame_key = GetFrameKey(node->current_frame_host()); |
| + if (!matches_only || matches_per_frame_.find(frame_key)->second || |
| + pending_replies_.count(frame_key)) { |
| + // Note that if there is still a pending reply expected for this frame, |
| + // then it may have unaccounted matches and will not be skipped via |
| + // |matches_only|. |
| + return node->current_frame_host(); |
| + } |
| + if (wrap && node->current_frame_host() == rfh) |
| + 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.
|
| + } |
| + |
| + return nullptr; |
| +} |
| + |
| +void FindRequestManager::AddFrame(RenderFrameHost* rfh) { |
| + FrameKey frame_key = GetFrameKey(rfh); |
| + // A frame that is already being searched should not be added again. |
| + DCHECK(!CheckFrame(frame_key)); |
| + |
| + matches_per_frame_[frame_key] = 0; |
| + |
| + FindRequest request = current_request_; |
| + request.id = current_session_id_; |
| + request.options.findNext = false; |
| + SendFindIPC(request, rfh); |
| +} |
| + |
| +bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const { |
| + return rfh ? CheckFrame(GetFrameKey(rfh)) : false; |
| +} |
| + |
| +bool FindRequestManager::CheckFrame(const FrameKey& frame_key) const { |
| + return matches_per_frame_.count(frame_key) == 1; |
| +} |
| + |
| +void FindRequestManager::UpdateActiveMatchOrdinal() { |
| + if (relative_active_match_ordinal_.first.first == kInvalidId || |
| + relative_active_match_ordinal_.first.second == kInvalidId || |
| + relative_active_match_ordinal_.second == 0) { |
| + active_match_ordinal_ = 0; |
| + return; |
| + } |
| + |
| + RenderFrameHost* rfh = |
| + GetRenderFrameHost(relative_active_match_ordinal_.first); |
| + if (!rfh) { |
| + RemoveFrame(relative_active_match_ordinal_.first); |
| + active_match_ordinal_ = 0; |
| + return; |
| + } |
| + |
| + // Traverse the frame tree backwards (in search order) and count all of the |
| + // matches in frames before the frame with the active match, in order to |
| + // determine the overall active match ordinal. |
| + active_match_ordinal_ = 0; |
| + while ((rfh = Traverse(rfh, |
| + false /* forward */, |
| + true /* matches_only */, |
| + false /* wrap */)) != nullptr) { |
| + active_match_ordinal_ += matches_per_frame_[GetFrameKey(rfh)]; |
| + } |
| + active_match_ordinal_ += relative_active_match_ordinal_.second; |
| +} |
| + |
| +void FindRequestManager::FinalUpdate(int request_id, RenderFrameHost* rfh) { |
| + if (!number_of_matches_ || pending_active_match_ordinal_ != request_id) { |
| + NotifyFindReply(request_id, true /* final_update */); |
| + AdvanceQueue(request_id); |
| + return; |
| + } |
| + |
| + // There are matches, but no active match was returned, so another find next |
| + // request must be sent. |
| + |
| + DCHECK_EQ(request_id, current_request_.id); |
| + RenderFrameHost* target_rfh; |
| + if (current_request_.options.findNext) { |
| + // If this was a find next operation, then the active match will be in the |
| + // next frame with matches after this one. |
| + target_rfh = Traverse(static_cast<RenderFrameHostImpl*>(rfh), |
| + current_request_.options.forward, |
| + true /* matches_only */, |
| + true /* wrap */); |
| + } else if ((target_rfh = contents_->GetFocusedFrame()) != nullptr) { |
| + // Otherwise, if there is a focused frame, then the active match will be in |
| + // the next frame with matches after that one. |
| + target_rfh = Traverse(target_rfh, |
| + current_request_.options.forward, |
| + true /* matches_only */, |
| + true /* wrap */); |
| + } else { |
| + // Otherwise, the first frame with matches will have the active match. |
| + target_rfh = GetInitialFrame(current_request_.options.forward); |
| + if (!CheckFrame(target_rfh) || |
| + !matches_per_frame_[GetFrameKey(target_rfh)]) { |
| + target_rfh = Traverse(target_rfh, |
| + current_request_.options.forward, |
| + true /* matches_only */, |
| + false /* wrap */); |
| + } |
| + } |
| + DCHECK(target_rfh); |
| + |
| + // Forward the find reply without |final_update| set because the active match |
| + // has not yet been found. |
| + NotifyFindReply(request_id, false /* final_update */); |
| + |
| + current_request_.options.findNext = true; |
| + SendFindIPC(current_request_, target_rfh); |
| +} |
| + |
| #if defined(OS_ANDROID) |
| +void FindRequestManager::SendGetNearestFindResultIPC(RenderFrameHost* rfh) { |
| + FrameKey frame_key = GetFrameKey(rfh); |
| + if (!CheckFrame(frame_key)) |
| + return; |
| + |
| + activate_.pending_replies.insert(GetFrameKey(rfh)); |
| + rfh->Send(new FrameMsg_GetNearestFindResult( |
| + rfh->GetRoutingID(), activate_.current_request_id, |
| + activate_.x, activate_.y)); |
| +} |
| + |
| +void FindRequestManager::RemoveNearestFindResultPendingReply( |
| + FrameKey frame_key) { |
| + auto it = activate_.pending_replies.find(frame_key); |
| + if (it != activate_.pending_replies.end()) { |
| + activate_.pending_replies.erase(it); |
| + if (activate_.pending_replies.empty() && |
| + CheckFrame(activate_.nearest_frame)) { |
| + RenderFrameHostImpl* rfh = GetRenderFrameHost(activate_.nearest_frame); |
| + rfh->Send(new FrameMsg_ActivateNearestFindResult( |
| + rfh->GetRoutingID(), current_session_id_, activate_.x, activate_.y)); |
| + } |
| + } |
| +} |
| + |
| void FindRequestManager::SendFindMatchRectsIPC(RenderFrameHost* rfh) { |
| - rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), |
| - match_rects_.request_version)); |
| + FrameKey frame_key = GetFrameKey(rfh); |
| + if (!CheckFrame(frame_key)) |
| + return; |
| + |
| + match_rects_.pending_replies.insert(frame_key); |
| + auto it = match_rects_.rects.find(frame_key); |
| + int version = |
| + (it != match_rects_.rects.end()) ? it->second.first : kInvalidId; |
| + rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version)); |
| +} |
| + |
| +void FindRequestManager::RemoveFindMatchRectsPendingReply(FrameKey frame_key) { |
| + auto it = match_rects_.pending_replies.find(frame_key); |
| + if (it == match_rects_.pending_replies.end()) |
| + return; |
| + |
| + match_rects_.pending_replies.erase(it); |
| + if (match_rects_.pending_replies.empty()) { |
| + // All replies are in. |
| + std::vector<gfx::RectF> rects; |
| + if (match_rects_.request_version != match_rects_.known_version) { |
| + // Request version is stale, so aggregate and report the newer find |
| + // match rects. |
| + for (auto& entry : match_rects_.rects) { |
| + std::vector<gfx::RectF>& frame_rects = entry.second.second; |
| + rects.insert(rects.end(), frame_rects.begin(), frame_rects.end()); |
| + } |
| + } |
| + contents_->NotifyFindMatchRectsReply( |
| + match_rects_.known_version, rects, match_rects_.active_rect); |
| + } |
| } |
| #endif |