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

Unified Diff: components/web_view/find_controller.cc

Issue 1371773003: mandoline: Add find in page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to ToT Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: components/web_view/find_controller.cc
diff --git a/components/web_view/find_controller.cc b/components/web_view/find_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d129d6f75783ee7e9d41672ff8ad9f40443f7a74
--- /dev/null
+++ b/components/web_view/find_controller.cc
@@ -0,0 +1,155 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/web_view/find_controller.h"
+
+#include "base/bind.h"
+#include "components/web_view/find_controller_delegate.h"
+#include "components/web_view/frame.h"
+
+namespace web_view {
+
+FindController::FindController(FindControllerDelegate* delegate)
+ : delegate_(delegate), current_find_request_(-1), weak_ptr_factory_(this) {}
+
+FindController::~FindController() {}
+
+void FindController::Find(int32_t request_id, const mojo::String& search_text) {
+ // TODO(erg): While this deals with multiple frames, it does not deal with
+ // going forward or backwards. To do that, we'll have to port all frame
+ // traversal and focusing concepts from blink::WebFrame to mojo::Frame.
+
+ // TODO(erg): This isn't great and causes flashes on character
+ // entry. However, it's needed for now because the internals of TextFinder
+ // still track the entire state of the blink frame tree, and if there are any
+ // frames that have marked text, doing a find clears the results of all
+ // frames _except_ for the first frame that it finds a result on.
+ StopFinding();
+
+ // TODO(erg): This cheap method does not traverse in the order that blink
+ // does.
+ pending_find_frames_ = delegate_->GetAllFrames();
+
+ current_find_request_ = request_id;
+ returned_find_data_.clear();
+
+ // Prime the continue loop.
+ OnContinueFinding(request_id, search_text, false);
+}
+
+void FindController::StopFinding() {
+ // Don't report any callbacks that we get after this.
+ current_find_request_ = -1;
+
+ for (Frame* f : delegate_->GetAllFrames())
+ f->StopFinding(true);
+}
+
+void FindController::OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update) {
+ if (request_id != current_find_request_)
+ return;
+
+ auto it = returned_find_data_.find(frame);
+ if (it == returned_find_data_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ it->second.count = count;
+ it->second.final_update = final_update;
+
+ int merged_count = 0;
+ bool merged_final_update = true;
+ for (auto const& data : returned_find_data_) {
+ merged_count += data.second.count;
+ merged_final_update = merged_final_update && data.second.final_update;
+ }
+
+ // We can now take the individual FindInFrame messages and construct a
+ // FindInPage message.
+ delegate_->GetWebViewClient()->FindInPageMatchCountUpdated(
+ request_id, merged_count, merged_final_update);
+}
+
+void FindController::OnFindInPageSelectionUpdated(
+ int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal) {
+ if (request_id != current_find_request_)
+ return;
+
+ // TODO(erg): This is the one that's really hard. To give an accurate count
+ // here, we need to have all the results for frames that are before the Frame
+ // that contains the selected match so we can add their sums together.
+ //
+ // Thankfully, we don't have to worry about this now. Since there aren't
+ // back/forward controls yet, active_match_ordinal will always be 1.
+ delegate_->GetWebViewClient()->FindInPageSelectionUpdated(
+ request_id, active_match_ordinal);
+}
+
+void FindController::DidDestroyFrame(Frame* frame) {
+ auto it =
+ find(pending_find_frames_.begin(), pending_find_frames_.end(), frame);
+ if (it != pending_find_frames_.end())
+ pending_find_frames_.erase(it);
+}
+
+void FindController::OnContinueFinding(int32_t request_id,
+ const mojo::String& search_text,
+ bool found) {
+ if (!found && !pending_find_frames_.empty()) {
+ // No match found, search on the next frame.
+ Frame* next_frame = pending_find_frames_.front();
+ pending_find_frames_.pop_front();
+ next_frame->Find(
+ request_id, search_text,
+ base::Bind(&FindController::OnContinueFinding,
+ weak_ptr_factory_.GetWeakPtr(), request_id, search_text));
+
+ // TODO(erg): This doesn't deal with wrapping around the document at the
+ // end when there are multiple frames.
+ return;
+ }
+
+ pending_find_frames_.clear();
+
+ // We either found a match or we got the final rejection. Either way, we
+ // alert our caller.
+
+ // If nothing is found, set result to "0 of 0", otherwise, set it to
+ // "-1 of 1" to indicate that we found at least one item, but we don't know
+ // yet what is active.
+ int ordinal = found ? -1 : 0; // -1 here means, we might know more later.
+ int match_count = found ? 1 : 0; // 1 here means possibly more coming.
+
+ // If we find no matches then this will be our last status update.
+ // Otherwise the scoping effort will send more results.
+ bool final_status_update = !found;
+
+ // Send priming messages.
+ delegate_->GetWebViewClient()->FindInPageSelectionUpdated(request_id,
+ ordinal);
+ delegate_->GetWebViewClient()->FindInPageMatchCountUpdated(
+ request_id, match_count, final_status_update);
+
+ // TODO(erg): This doesn't iterate in the same order as the current code
+ // because we don't have the correct iteration primitives.
+ std::deque<Frame*> frames = delegate_->GetAllFrames();
+ for (Frame* f : frames) {
+ f->StopHighlightingFindResults();
+
+ if (found) {
+ MatchData& match_data = returned_find_data_[f];
+ match_data.count = 0;
+ match_data.final_update = false;
+ f->HighlightFindResults(request_id, search_text, true);
+ }
+ }
+}
+
+} // namespace web_view

Powered by Google App Engine
This is Rietveld 408576698