| 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:
|
|
|
|
|