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

Unified Diff: components/web_view/web_view_impl.cc

Issue 1371773003: mandoline: Add find in page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to ToT to fix patch failure. Created 5 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 side-by-side diff with in-line comments
Download patch
Index: components/web_view/web_view_impl.cc
diff --git a/components/web_view/web_view_impl.cc b/components/web_view/web_view_impl.cc
index 8992496bbc2789309aa2883afe1d67c9f21a474b..7df54d48e9a5fe500d5f1c01a0ca0f193557133f 100644
--- a/components/web_view/web_view_impl.cc
+++ b/components/web_view/web_view_impl.cc
@@ -4,6 +4,9 @@
#include "components/web_view/web_view_impl.h"
+#include <queue>
+
+#include "base/bind.h"
#include "base/command_line.h"
#include "components/devtools_service/public/cpp/switches.h"
#include "components/mus/public/cpp/scoped_view_ptr.h"
@@ -44,7 +47,8 @@ WebViewImpl::WebViewImpl(mojo::ApplicationImpl* app,
binding_(this, request.Pass()),
root_(nullptr),
content_(nullptr),
- navigation_controller_(this) {
+ navigation_controller_(this),
+ current_find_request_(-1) {
if (EnableRemoteDebugging())
devtools_agent_.reset(new FrameDevToolsAgent(app_, this));
OnDidNavigate();
@@ -98,6 +102,73 @@ void WebViewImpl::OnLoad(const GURL& pending_url) {
frame_connection.Pass(), client_properties));
}
+std::deque<Frame*> WebViewImpl::GetAllFrames() {
+ std::deque<Frame*> all_frames;
+ std::queue<Frame*> frames_to_search;
+ frames_to_search.push(frame_tree_->root());
+ while (!frames_to_search.empty()) {
+ // TODO(erg): This is not in depth first order. I'm not actually sure how
+ // blink does traversal though.
+ Frame* current = frames_to_search.front();
+ frames_to_search.pop();
+ for (Frame* child : current->children())
+ frames_to_search.push(child);
+ all_frames.push_back(current);
+ }
+ return all_frames;
+}
+
+void WebViewImpl::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(&WebViewImpl::OnContinueFinding,
+ base::Unretained(this)));
+
+ // 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.
+ client_->ReportFindInPageSelection(request_id, ordinal);
+ client_->ReportFindInPageMatchCount(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 = GetAllFrames();
+ for (Frame* f : frames) {
+ f->CancelPendingScopingEffort();
+
+ if (found) {
+ MatchData& match_data = returned_find_data_[f];
+ match_data.count = 0;
+ match_data.final_update = false;
+ f->ScopeStringMatches(request_id, search_text, true);
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebViewImpl, WebView implementation:
@@ -110,6 +181,41 @@ void WebViewImpl::GetViewTreeClient(
mus::ViewTreeConnection::Create(this, view_tree_client.Pass());
}
+void WebViewImpl::Find(int32_t request_id, const mojo::String& search_text) {
+ DCHECK(frame_tree_);
+
+ // 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_ = GetAllFrames();
+
+ current_find_request_ = request_id;
+ returned_find_data_.clear();
+
+ // Prime the continue loop.
+ OnContinueFinding(request_id, search_text, false);
+}
+
+void WebViewImpl::StopFinding() {
+ DCHECK(frame_tree_);
+
+ // Don't report any callbacks that we get after this.
+ current_find_request_ = -1;
+
+ for (Frame* f : GetAllFrames())
+ f->StopFinding(true);
+}
+
void WebViewImpl::GoBack() {
if (!navigation_controller_.CanGoBack())
return;
@@ -203,6 +309,58 @@ void WebViewImpl::DidCommitProvisionalLoad(Frame* frame) {
navigation_controller_.FrameDidCommitProvisionalLoad(frame);
}
+void WebViewImpl::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 WebViewImpl::OnReportFindInFrameMatchCount(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.
+ client_->ReportFindInPageMatchCount(request_id,
+ merged_count,
+ merged_final_update);
+}
+
+void WebViewImpl::OnReportFindInPageSelection(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.
+ client_->ReportFindInPageSelection(request_id, active_match_ordinal);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebViewImpl, FrameDevToolsAgentDelegate implementation:

Powered by Google App Engine
This is Rietveld 408576698