OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "components/web_view/find_controller.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "components/web_view/find_controller_delegate.h" |
| 9 #include "components/web_view/frame.h" |
| 10 |
| 11 namespace web_view { |
| 12 |
| 13 FindController::FindController(FindControllerDelegate* delegate) |
| 14 : delegate_(delegate), |
| 15 current_find_request_(-1), |
| 16 weak_ptr_factory_(this) {} |
| 17 |
| 18 FindController::~FindController() {} |
| 19 |
| 20 void FindController::Find(int32_t request_id, const mojo::String& search_text) { |
| 21 // TODO(erg): While this deals with multiple frames, it does not deal with |
| 22 // going forward or backwards. To do that, we'll have to port all frame |
| 23 // traversal and focusing concepts from blink::WebFrame to mojo::Frame. |
| 24 |
| 25 // TODO(erg): This isn't great and causes flashes on character |
| 26 // entry. However, it's needed for now because the internals of TextFinder |
| 27 // still track the entire state of the blink frame tree, and if there are any |
| 28 // frames that have marked text, doing a find clears the results of all |
| 29 // frames _except_ for the first frame that it finds a result on. |
| 30 StopFinding(); |
| 31 |
| 32 // TODO(erg): This cheap method does not traverse in the order that blink |
| 33 // does. |
| 34 pending_find_frames_ = delegate_->GetAllFrames(); |
| 35 |
| 36 current_find_request_ = request_id; |
| 37 returned_find_data_.clear(); |
| 38 |
| 39 // Prime the continue loop. |
| 40 OnContinueFinding(request_id, search_text, false); |
| 41 } |
| 42 |
| 43 void FindController::StopFinding() { |
| 44 // Don't report any callbacks that we get after this. |
| 45 current_find_request_ = -1; |
| 46 |
| 47 for (Frame* f : delegate_->GetAllFrames()) |
| 48 f->StopFinding(true); |
| 49 } |
| 50 |
| 51 void FindController::OnReportFindInFrameMatchCount(int32_t request_id, |
| 52 Frame* frame, |
| 53 int32_t count, |
| 54 bool final_update) { |
| 55 if (request_id != current_find_request_) |
| 56 return; |
| 57 |
| 58 auto it = returned_find_data_.find(frame); |
| 59 if (it == returned_find_data_.end()) { |
| 60 NOTREACHED(); |
| 61 return; |
| 62 } |
| 63 |
| 64 it->second.count = count; |
| 65 it->second.final_update = final_update; |
| 66 |
| 67 int merged_count = 0; |
| 68 bool merged_final_update = true; |
| 69 for (auto const& data : returned_find_data_) { |
| 70 merged_count += data.second.count; |
| 71 merged_final_update = merged_final_update && data.second.final_update; |
| 72 } |
| 73 |
| 74 // We can now take the individual FindInFrame messages and construct a |
| 75 // FindInPage message. |
| 76 delegate_->GetWebViewClient()->ReportFindInPageMatchCount( |
| 77 request_id, merged_count, merged_final_update); |
| 78 } |
| 79 |
| 80 void FindController::OnReportFindInPageSelection(int32_t request_id, |
| 81 Frame* frame, |
| 82 int32_t active_match_ordinal) { |
| 83 if (request_id != current_find_request_) |
| 84 return; |
| 85 |
| 86 // TODO(erg): This is the one that's really hard. To give an accurate count |
| 87 // here, we need to have all the results for frames that are before the Frame |
| 88 // that contains the selected match so we can add their sums together. |
| 89 // |
| 90 // Thankfully, we don't have to worry about this now. Since there aren't |
| 91 // back/forward controls yet, active_match_ordinal will always be 1. |
| 92 delegate_->GetWebViewClient()->ReportFindInPageSelection( |
| 93 request_id, active_match_ordinal); |
| 94 } |
| 95 |
| 96 void FindController::DidDestroyFrame(Frame* frame) { |
| 97 auto it = |
| 98 find(pending_find_frames_.begin(), pending_find_frames_.end(), frame); |
| 99 if (it != pending_find_frames_.end()) |
| 100 pending_find_frames_.erase(it); |
| 101 } |
| 102 |
| 103 void FindController::OnContinueFinding(int32_t request_id, |
| 104 const mojo::String& search_text, |
| 105 bool found) { |
| 106 if (!found && !pending_find_frames_.empty()) { |
| 107 // No match found, search on the next frame. |
| 108 Frame* next_frame = pending_find_frames_.front(); |
| 109 pending_find_frames_.pop_front(); |
| 110 next_frame->Find( |
| 111 request_id, search_text, |
| 112 base::Bind(&FindController::OnContinueFinding, |
| 113 weak_ptr_factory_.GetWeakPtr(), |
| 114 request_id, |
| 115 search_text)); |
| 116 |
| 117 // TODO(erg): This doesn't deal with wrapping around the document at the |
| 118 // end when there are multiple frames. |
| 119 return; |
| 120 } |
| 121 |
| 122 pending_find_frames_.clear(); |
| 123 |
| 124 // We either found a match or we got the final rejection. Either way, we |
| 125 // alert our caller. |
| 126 |
| 127 // If nothing is found, set result to "0 of 0", otherwise, set it to |
| 128 // "-1 of 1" to indicate that we found at least one item, but we don't know |
| 129 // yet what is active. |
| 130 int ordinal = found ? -1 : 0; // -1 here means, we might know more later. |
| 131 int match_count = found ? 1 : 0; // 1 here means possibly more coming. |
| 132 |
| 133 // If we find no matches then this will be our last status update. |
| 134 // Otherwise the scoping effort will send more results. |
| 135 bool final_status_update = !found; |
| 136 |
| 137 // Send priming messages. |
| 138 delegate_->GetWebViewClient()->ReportFindInPageSelection(request_id, ordinal); |
| 139 delegate_->GetWebViewClient()->ReportFindInPageMatchCount( |
| 140 request_id, match_count, final_status_update); |
| 141 |
| 142 // TODO(erg): This doesn't iterate in the same order as the current code |
| 143 // because we don't have the correct iteration primitives. |
| 144 std::deque<Frame*> frames = delegate_->GetAllFrames(); |
| 145 for (Frame* f : frames) { |
| 146 f->CancelPendingScopingEffort(); |
| 147 |
| 148 if (found) { |
| 149 MatchData& match_data = returned_find_data_[f]; |
| 150 match_data.count = 0; |
| 151 match_data.final_update = false; |
| 152 f->ScopeStringMatches(request_id, search_text, true); |
| 153 } |
| 154 } |
| 155 } |
| 156 |
| 157 } // namespace web_view |
OLD | NEW |