summaryrefslogtreecommitdiffstats
path: root/components/web_view
diff options
context:
space:
mode:
authorerg <erg@chromium.org>2015-10-05 21:30:38 -0700
committerCommit bot <commit-bot@chromium.org>2015-10-06 04:33:07 +0000
commitfe308b3359314164d5a74633dfbcf52c6367630b (patch)
treed16c9bcbf9b7fd7887a22a8e09f4f70dad042359 /components/web_view
parent6d5f60a81ff97645015695c4289523d0007defa4 (diff)
downloadchromium_src-fe308b3359314164d5a74633dfbcf52c6367630b.zip
chromium_src-fe308b3359314164d5a74633dfbcf52c6367630b.tar.gz
chromium_src-fe308b3359314164d5a74633dfbcf52c6367630b.tar.bz2
mandoline: Add find in page.
This adds Ctrl+F as a keyboard shortcut to replace the current toolbar with a find in page bar, where the user can enter some text. BUG=496978 Review URL: https://codereview.chromium.org/1371773003 Cr-Commit-Position: refs/heads/master@{#352535}
Diffstat (limited to 'components/web_view')
-rw-r--r--components/web_view/BUILD.gn2
-rw-r--r--components/web_view/find_controller.cc155
-rw-r--r--components/web_view/find_controller.h78
-rw-r--r--components/web_view/find_controller_delegate.h29
-rw-r--r--components/web_view/frame.cc33
-rw-r--r--components/web_view/frame.h15
-rw-r--r--components/web_view/frame_apptest.cc8
-rw-r--r--components/web_view/frame_tree_delegate.cc8
-rw-r--r--components/web_view/frame_tree_delegate.h9
-rw-r--r--components/web_view/public/interfaces/frame.mojom39
-rw-r--r--components/web_view/public/interfaces/web_view.mojom11
-rw-r--r--components/web_view/test_runner/test_runner_application_delegate.h5
-rw-r--r--components/web_view/web_view_apptest.cc65
-rw-r--r--components/web_view/web_view_impl.cc56
-rw-r--r--components/web_view/web_view_impl.h22
15 files changed, 526 insertions, 9 deletions
diff --git a/components/web_view/BUILD.gn b/components/web_view/BUILD.gn
index 5b634e2..f86231c 100644
--- a/components/web_view/BUILD.gn
+++ b/components/web_view/BUILD.gn
@@ -15,6 +15,8 @@ source_set("lib") {
sources = [
"client_initiated_frame_connection.cc",
"client_initiated_frame_connection.h",
+ "find_controller.cc",
+ "find_controller.h",
"frame.cc",
"frame.h",
"frame_connection.cc",
diff --git a/components/web_view/find_controller.cc b/components/web_view/find_controller.cc
new file mode 100644
index 0000000..d129d6f
--- /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
diff --git a/components/web_view/find_controller.h b/components/web_view/find_controller.h
new file mode 100644
index 0000000..186d393
--- /dev/null
+++ b/components/web_view/find_controller.h
@@ -0,0 +1,78 @@
+// 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.
+
+#ifndef COMPONENTS_WEB_VIEW_FIND_CONTROLLER_H_
+#define COMPONENTS_WEB_VIEW_FIND_CONTROLLER_H_
+
+#include <deque>
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "components/web_view/public/interfaces/web_view.mojom.h"
+
+namespace web_view {
+
+class FindControllerDelegate;
+class Frame;
+
+// Contains all the find code used by WebViewImpl.
+class FindController {
+ public:
+ FindController(FindControllerDelegate* delegate);
+ ~FindController();
+
+ // Starts a find session looking for |search_text|. This method will first
+ // scan through frames one by one to look for the first instance of
+ // |search_text|, and return the data through
+ // OnFindInPageSelectionUpdated(). If found, it will highlight all instances
+ // of the text and report the final total count through
+ // FindInPageMatchCountUpdated().
+ void Find(int32_t request_id, const mojo::String& search_text);
+
+ // Unhighlights all find instances on the page.
+ void StopFinding();
+
+ void OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update);
+ void OnFindInPageSelectionUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal);
+
+ void DidDestroyFrame(Frame* frame);
+
+ private:
+ struct MatchData {
+ int count;
+ bool final_update;
+ };
+
+ // Callback method invoked by Find().
+ void OnContinueFinding(int32_t request_id,
+ const mojo::String& search_text,
+ bool found);
+
+ // Our owner.
+ FindControllerDelegate* delegate_;
+
+ // A list of Frames which we have not sent a Find() command to. Initialized
+ // in Find(), and read from OnContinueFinding().
+ std::deque<Frame*> pending_find_frames_;
+
+ // Current find session number. We keep track of this to prevent recording
+ // stale callbacks.
+ int current_find_request_;
+
+ // The current callback data from various frames.
+ std::map<Frame*, MatchData> returned_find_data_;
+
+ base::WeakPtrFactory<FindController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FindController);
+};
+
+} // namespace web_view
+
+#endif // COMPONENTS_WEB_VIEW_FIND_CONTROLLER_H_
diff --git a/components/web_view/find_controller_delegate.h b/components/web_view/find_controller_delegate.h
new file mode 100644
index 0000000..56f1d16
--- /dev/null
+++ b/components/web_view/find_controller_delegate.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef COMPONENTS_WEB_VIEW_FIND_CONTROLLER_DELEGATE_H_
+#define COMPONENTS_WEB_VIEW_FIND_CONTROLLER_DELEGATE_H_
+
+#include <deque>
+
+namespace mojom {
+class WebViewClient;
+}
+
+namespace web_view {
+
+class Frame;
+
+class FindControllerDelegate {
+ public:
+ ~FindControllerDelegate() {}
+
+ virtual std::deque<Frame*> GetAllFrames() = 0;
+
+ virtual mojom::WebViewClient* GetWebViewClient() = 0;
+};
+
+} // namespace web_view
+
+#endif // COMPONENTS_WEB_VIEW_FIND_CONTROLLER_DELEGATE_H_
diff --git a/components/web_view/frame.cc b/components/web_view/frame.cc
index e5f82f5..93232af 100644
--- a/components/web_view/frame.cc
+++ b/components/web_view/frame.cc
@@ -161,6 +161,26 @@ double Frame::GatherProgress(int* frame_count) const {
return progress_;
}
+void Frame::Find(int32 request_id,
+ const mojo::String& search_text,
+ const FindCallback& callback) {
+ frame_client_->Find(request_id, search_text, callback);
+}
+
+void Frame::StopFinding(bool clear_selection) {
+ frame_client_->StopFinding(clear_selection);
+}
+
+void Frame::HighlightFindResults(int32_t request_id,
+ const mojo::String& search_text,
+ bool reset) {
+ frame_client_->HighlightFindResults(request_id, search_text, reset);
+}
+
+void Frame::StopHighlightingFindResults() {
+ frame_client_->StopHighlightingFindResults();
+}
+
void Frame::InitClient(ClientType client_type,
scoped_ptr<FrameUserDataAndBinding> data_and_binding,
mojo::ViewTreeClientPtr view_tree_client,
@@ -543,4 +563,17 @@ void Frame::DispatchLoadEventToParent() {
}
}
+void Frame::OnFindInFrameCountUpdated(int32_t request_id,
+ int32_t count,
+ bool final_update) {
+ tree_->delegate_->OnFindInFrameCountUpdated(request_id, this, count,
+ final_update);
+}
+
+void Frame::OnFindInPageSelectionUpdated(int32_t request_id,
+ int32_t active_match_ordinal) {
+ tree_->delegate_->OnFindInPageSelectionUpdated(request_id, this,
+ active_match_ordinal);
+}
+
} // namespace web_view
diff --git a/components/web_view/frame.h b/components/web_view/frame.h
index 380bc8e..f0756df0 100644
--- a/components/web_view/frame.h
+++ b/components/web_view/frame.h
@@ -54,6 +54,7 @@ enum class ViewOwnership {
class Frame : public mus::ViewObserver, public mojom::Frame {
public:
using ClientPropertyMap = std::map<std::string, std::vector<uint8_t>>;
+ using FindCallback = mojo::Callback<void(bool)>;
Frame(FrameTree* tree,
mus::View* view,
@@ -112,6 +113,15 @@ class Frame : public mus::ViewObserver, public mojom::Frame {
// children, as well as the number of Frames accumulated.
double GatherProgress(int* frame_count) const;
+ void Find(int32_t request_id,
+ const mojo::String& search_text,
+ const FindCallback& callback);
+ void StopFinding(bool clear_selection);
+ void HighlightFindResults(int32_t request_id,
+ const mojo::String& search_text,
+ bool reset);
+ void StopHighlightingFindResults();
+
private:
friend class FrameTest;
friend class FrameTree;
@@ -224,6 +234,11 @@ class Frame : public mus::ViewObserver, public mojom::Frame {
mojo::URLRequestPtr request) override;
void DidNavigateLocally(const mojo::String& url) override;
void DispatchLoadEventToParent() override;
+ void OnFindInFrameCountUpdated(int32_t request_id,
+ int32_t count,
+ bool final_update) override;
+ void OnFindInPageSelectionUpdated(int32_t request_id,
+ int32_t active_match_ordinal) override;
FrameTree* const tree_;
// WARNING: this may be null. See class description for details.
diff --git a/components/web_view/frame_apptest.cc b/components/web_view/frame_apptest.cc
index fb6171d..40c31bf 100644
--- a/components/web_view/frame_apptest.cc
+++ b/components/web_view/frame_apptest.cc
@@ -166,6 +166,14 @@ class TestFrameClient : public mojom::FrameClient {
if (!on_dispatch_load_event_callback_.is_null())
on_dispatch_load_event_callback_.Run();
}
+ void Find(int32_t request_id,
+ const mojo::String& search_text,
+ const FindCallback& callback) override {}
+ void StopFinding(bool clear_selection) override {}
+ void HighlightFindResults(int32_t request_id,
+ const mojo::String& search_test,
+ bool reset) override {}
+ void StopHighlightingFindResults() override {}
private:
struct LoadingStateChangedNotification {
diff --git a/components/web_view/frame_tree_delegate.cc b/components/web_view/frame_tree_delegate.cc
index ab7e8d3..c04ec70 100644
--- a/components/web_view/frame_tree_delegate.cc
+++ b/components/web_view/frame_tree_delegate.cc
@@ -9,5 +9,13 @@ namespace web_view {
void FrameTreeDelegate::DidCreateFrame(Frame* frame) {}
void FrameTreeDelegate::DidDestroyFrame(Frame* frame) {}
void FrameTreeDelegate::OnViewEmbeddedInFrameDisconnected(Frame* frame) {}
+void FrameTreeDelegate::OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update) {}
+void FrameTreeDelegate::OnFindInPageSelectionUpdated(
+ int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal) {}
} // namespace web_view
diff --git a/components/web_view/frame_tree_delegate.h b/components/web_view/frame_tree_delegate.h
index d14fe72..b1eab678 100644
--- a/components/web_view/frame_tree_delegate.h
+++ b/components/web_view/frame_tree_delegate.h
@@ -84,6 +84,15 @@ class FrameTreeDelegate {
// action.
virtual void OnViewEmbeddedInFrameDisconnected(Frame* frame);
+ // Reports the current find state back to our owner.
+ virtual void OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update);
+ virtual void OnFindInPageSelectionUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal);
+
protected:
virtual ~FrameTreeDelegate() {}
};
diff --git a/components/web_view/public/interfaces/frame.mojom b/components/web_view/public/interfaces/frame.mojom
index d1a8f80..ffe1f8f 100644
--- a/components/web_view/public/interfaces/frame.mojom
+++ b/components/web_view/public/interfaces/frame.mojom
@@ -110,6 +110,14 @@ interface Frame {
// Dispatches a load event to the parent of the frame.
DispatchLoadEventToParent();
+
+ // Reports the number of matches for a given find. This is an asynchronous
+ // notification and can fire multiple times per HighlightFindResults() call.
+ OnFindInFrameCountUpdated(int32 request_id, int32 count,
+ bool final_update);
+
+ // Reports which match is currently highlighted.
+ OnFindInPageSelectionUpdated(int32 request_id, int32 active_match_ordinal);
};
enum ViewConnectType {
@@ -166,4 +174,35 @@ interface FrameClient {
// Called to dispatch a load event of |frame_id| in its parent. This is only
// called on the FrameClient rendering the parent of |frame_id|.
OnDispatchFrameLoadEvent(uint32 frame_id);
+
+ // TODO(erg): Several of these take a WebFindOptions struct; we probably need
+ // to build a Frame version of that struct.
+
+ // Searches for a given string. If a match is found, it will be
+ // selected. Find() will only return true if it found a match, and will return
+ // the result in the future through OnFindInPageSelectionUpdated(). That
+ // callback will return |request_id|, and the listener should verify the
+ // |request_id| on callback to guard against race conditions.
+ //
+ // |request_id| should be a monotonically increasing number which should only
+ // be reused between Find() and the HighlightFindResults() calls that are
+ // searching for the same string. |search_text| may be empty.
+ Find(int32 request_id, string search_text) => (bool found);
+
+ // Stop finding the single find result on the page. If |clear_selection| is
+ // set, it will also clear the selected find text.
+ StopFinding(bool clear_selection);
+
+ // Match every instance of a string in a document asynchronously, highlighting
+ // them and putting a tick mark in the scroll bar. This differs from Find() as
+ // Find() is about finding the one selected instance of the text.
+ // HighlightFindResults() is about highlighting all the instances of the text.
+ //
+ // HighlightFindResults() will asynchronously call
+ // OnFindInFrameCountUpdated() multiple times to report its progress.
+ HighlightFindResults(int32 request_id, string search_test, bool reset);
+
+ // Removes the tick marks and highlighting done by HighlightFindResults() in
+ // this frame.
+ StopHighlightingFindResults();
};
diff --git a/components/web_view/public/interfaces/web_view.mojom b/components/web_view/public/interfaces/web_view.mojom
index 1385b8d..788b554 100644
--- a/components/web_view/public/interfaces/web_view.mojom
+++ b/components/web_view/public/interfaces/web_view.mojom
@@ -27,6 +27,13 @@ interface WebViewClient {
// TODO(beng): also forward text direction.
TitleChanged(string? title);
+
+ // Reports the number of matches for a given Find() call.
+ FindInPageMatchCountUpdated(int32 request_id, int32 count, bool final_update);
+
+ // Reports which find match is selected. (If there are five highlighted
+ // matches on a page, and the 2nd is selected, |active_match_ordinal| is 2.)
+ FindInPageSelectionUpdated(int32 request_id, int32 active_match_ordinal);
};
interface WebView {
@@ -36,6 +43,10 @@ interface WebView {
// Provide a ViewTreeClient for this specific WebView.
GetViewTreeClient(mojo.ViewTreeClient& view_tree_client);
+ // Finds a string in page.
+ Find(int32 request_id, string search_text);
+ StopFinding();
+
// Moves forward and backward.
GoBack();
GoForward();
diff --git a/components/web_view/test_runner/test_runner_application_delegate.h b/components/web_view/test_runner/test_runner_application_delegate.h
index 48327df..03d5b5e 100644
--- a/components/web_view/test_runner/test_runner_application_delegate.h
+++ b/components/web_view/test_runner/test_runner_application_delegate.h
@@ -55,6 +55,11 @@ class TestRunnerApplicationDelegate
void BackForwardChanged(mojom::ButtonState back_button,
mojom::ButtonState forward_button) override;
void TitleChanged(const mojo::String& title) override;
+ void FindInPageMatchCountUpdated(int32_t request_id,
+ int32_t count,
+ bool final_update) override {}
+ void FindInPageSelectionUpdated(int32_t request_id,
+ int32_t active_match_ordinal) override {}
// LayoutTestRunner:
void TestFinished() override;
diff --git a/components/web_view/web_view_apptest.cc b/components/web_view/web_view_apptest.cc
index 130ef0a..1aa84aa 100644
--- a/components/web_view/web_view_apptest.cc
+++ b/components/web_view/web_view_apptest.cc
@@ -26,6 +26,8 @@ const char kTestTwoFile[] = "test_two.html";
const char kTestTwoTitle[] = "Test Title Two";
const char kTestThreeFile[] = "test_three.html";
const char kTestThreeTitle[] = "Test Title Three";
+const char kTheWordGreenFiveTimes[] = "the_word_green_five_times.html";
+const char kTwoIframesWithGreen[] = "two_iframes_with_green.html";
GURL GetTestFileURL(const std::string& file) {
base::FilePath data_file;
@@ -41,7 +43,11 @@ GURL GetTestFileURL(const std::string& file) {
class WebViewTest : public mus::ViewManagerTestBase,
public mojom::WebViewClient {
public:
- WebViewTest() : web_view_(this) {}
+ WebViewTest()
+ : web_view_(this),
+ quit_condition_(NO_QUIT),
+ active_find_match_(0),
+ find_count_(0) {}
~WebViewTest() override {}
mojom::WebView* web_view() { return web_view_.web_view(); }
@@ -55,7 +61,17 @@ class WebViewTest : public mus::ViewManagerTestBase,
return last_forward_button_state_;
}
- void StartNestedRunLoopUntilLoadingDone() {
+ int32_t active_find_match() const { return active_find_match_; }
+ int32_t find_count() const { return find_count_; }
+
+ enum NestedLoopQuitCondition {
+ NO_QUIT,
+ LOADING_DONE,
+ FINAL_FIND_UPATE,
+ };
+
+ void StartNestedRunLoopUntil(NestedLoopQuitCondition quit_condition) {
+ quit_condition_ = quit_condition;
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
}
@@ -64,12 +80,13 @@ class WebViewTest : public mus::ViewManagerTestBase,
mojo::URLRequestPtr request(mojo::URLRequest::New());
request->url = GetTestFileURL(file).spec();
web_view()->LoadRequest(request.Pass());
- StartNestedRunLoopUntilLoadingDone();
+ StartNestedRunLoopUntil(LOADING_DONE);
}
private:
void QuitNestedRunLoop() {
if (run_loop_) {
+ quit_condition_ = NO_QUIT;
run_loop_->Quit();
}
}
@@ -83,6 +100,7 @@ class WebViewTest : public mus::ViewManagerTestBase,
// Overridden from ViewTreeDelegate:
void OnEmbed(mus::View* root) override {
content_ = root->connection()->CreateView();
+ content_->SetBounds(root->bounds());
root->AddChild(content_);
content_->SetVisible(true);
@@ -102,7 +120,7 @@ class WebViewTest : public mus::ViewManagerTestBase,
navigation_url_ = url.get();
}
void LoadingStateChanged(bool is_loading, double progress) override {
- if (is_loading == false)
+ if (is_loading == false && quit_condition_ == LOADING_DONE)
QuitNestedRunLoop();
}
void BackForwardChanged(mojom::ButtonState back_button,
@@ -113,6 +131,17 @@ class WebViewTest : public mus::ViewManagerTestBase,
void TitleChanged(const mojo::String& title) override {
last_title_ = title.get();
}
+ void FindInPageMatchCountUpdated(int32_t request_id,
+ int32_t count,
+ bool final_update) override {
+ find_count_ = count;
+ if (final_update && quit_condition_ == FINAL_FIND_UPATE)
+ QuitNestedRunLoop();
+ }
+ void FindInPageSelectionUpdated(int32_t request_id,
+ int32_t active_match_ordinal) override {
+ active_find_match_ = active_match_ordinal;
+ }
mojo::ApplicationImpl* app_;
@@ -127,6 +156,11 @@ class WebViewTest : public mus::ViewManagerTestBase,
mojom::ButtonState last_back_button_state_;
mojom::ButtonState last_forward_button_state_;
+ NestedLoopQuitCondition quit_condition_;
+
+ int32_t active_find_match_;
+ int32_t find_count_;
+
DISALLOW_COPY_AND_ASSIGN(WebViewTest);
};
@@ -157,7 +191,7 @@ TEST_F(WebViewTest, CanGoBackAndForward) {
last_forward_button_state());
web_view()->GoBack();
- StartNestedRunLoopUntilLoadingDone();
+ StartNestedRunLoopUntil(LOADING_DONE);
EXPECT_EQ(GetTestFileURL(kTestOneFile).spec(), navigation_url());
EXPECT_EQ(kTestOneTitle, last_title());
@@ -167,7 +201,7 @@ TEST_F(WebViewTest, CanGoBackAndForward) {
last_forward_button_state());
web_view()->GoForward();
- StartNestedRunLoopUntilLoadingDone();
+ StartNestedRunLoopUntil(LOADING_DONE);
EXPECT_EQ(GetTestFileURL(kTestTwoFile).spec(), navigation_url());
EXPECT_EQ(kTestTwoTitle, last_title());
EXPECT_EQ(mojom::ButtonState::BUTTON_STATE_ENABLED, last_back_button_state());
@@ -182,7 +216,7 @@ TEST_F(WebViewTest, NavigationClearsForward) {
ASSERT_NO_FATAL_FAILURE(NavigateTo(kTestTwoFile));
web_view()->GoBack();
- StartNestedRunLoopUntilLoadingDone();
+ StartNestedRunLoopUntil(LOADING_DONE);
EXPECT_EQ(GetTestFileURL(kTestOneFile).spec(), navigation_url());
EXPECT_EQ(kTestOneTitle, last_title());
@@ -201,4 +235,21 @@ TEST_F(WebViewTest, NavigationClearsForward) {
last_forward_button_state());
}
+TEST_F(WebViewTest, Find) {
+ ASSERT_NO_FATAL_FAILURE(NavigateTo(kTheWordGreenFiveTimes));
+
+ web_view()->Find(1, "Green");
+ StartNestedRunLoopUntil(FINAL_FIND_UPATE);
+ EXPECT_EQ(1, active_find_match());
+ EXPECT_EQ(5, find_count());
+}
+
+TEST_F(WebViewTest, FindAcrossIframes) {
+ ASSERT_NO_FATAL_FAILURE(NavigateTo(kTwoIframesWithGreen));
+
+ web_view()->Find(1, "Green");
+ StartNestedRunLoopUntil(FINAL_FIND_UPATE);
+ EXPECT_EQ(13, find_count());
+}
+
} // namespace web_view
diff --git a/components/web_view/web_view_impl.cc b/components/web_view/web_view_impl.cc
index 8992496..545fbe6 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),
+ find_controller_(this) {
if (EnableRemoteDebugging())
devtools_agent_.reset(new FrameDevToolsAgent(app_, this));
OnDidNavigate();
@@ -110,6 +114,14 @@ void WebViewImpl::GetViewTreeClient(
mus::ViewTreeConnection::Create(this, view_tree_client.Pass());
}
+void WebViewImpl::Find(int32_t request_id, const mojo::String& search_text) {
+ find_controller_.Find(request_id, search_text);
+}
+
+void WebViewImpl::StopFinding() {
+ find_controller_.StopFinding();
+}
+
void WebViewImpl::GoBack() {
if (!navigation_controller_.CanGoBack())
return;
@@ -203,6 +215,25 @@ void WebViewImpl::DidCommitProvisionalLoad(Frame* frame) {
navigation_controller_.FrameDidCommitProvisionalLoad(frame);
}
+void WebViewImpl::DidDestroyFrame(Frame* frame) {
+ find_controller_.DidDestroyFrame(frame);
+}
+
+void WebViewImpl::OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update) {
+ find_controller_.OnFindInFrameCountUpdated(request_id, frame, count,
+ final_update);
+}
+
+void WebViewImpl::OnFindInPageSelectionUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal) {
+ find_controller_.OnFindInPageSelectionUpdated(request_id, frame,
+ active_match_ordinal);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebViewImpl, FrameDevToolsAgentDelegate implementation:
@@ -229,4 +260,27 @@ void WebViewImpl::OnDidNavigate() {
: ButtonState::BUTTON_STATE_DISABLED);
}
+////////////////////////////////////////////////////////////////////////////////
+// WebViewImpl, FindControllerDelegate implementation:
+
+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;
+}
+
+mojom::WebViewClient* WebViewImpl::GetWebViewClient() {
+ return client_.get();
+}
+
} // namespace web_view
diff --git a/components/web_view/web_view_impl.h b/components/web_view/web_view_impl.h
index c7a49d4a..449fdd8 100644
--- a/components/web_view/web_view_impl.h
+++ b/components/web_view/web_view_impl.h
@@ -5,12 +5,15 @@
#ifndef COMPONENTS_WEB_VIEW_WEB_VIEW_IMPL_H_
#define COMPONENTS_WEB_VIEW_WEB_VIEW_IMPL_H_
+#include <deque>
#include <string>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "components/mus/public/cpp/view_observer.h"
#include "components/mus/public/cpp/view_tree_delegate.h"
+#include "components/web_view/find_controller.h"
+#include "components/web_view/find_controller_delegate.h"
#include "components/web_view/frame_devtools_agent_delegate.h"
#include "components/web_view/frame_tree_delegate.h"
#include "components/web_view/navigation_controller.h"
@@ -39,7 +42,8 @@ class WebViewImpl : public mojom::WebView,
public mus::ViewObserver,
public FrameTreeDelegate,
public FrameDevToolsAgentDelegate,
- public NavigationControllerDelegate {
+ public NavigationControllerDelegate,
+ public FindControllerDelegate {
public:
WebViewImpl(mojo::ApplicationImpl* app,
mojom::WebViewClientPtr client,
@@ -57,6 +61,8 @@ class WebViewImpl : public mojom::WebView,
void GetViewTreeClient(
mojo::InterfaceRequest<mojo::ViewTreeClient> view_tree_client)
override;
+ void Find(int32_t request_id, const mojo::String& search_text) override;
+ void StopFinding() override;
void GoBack() override;
void GoForward() override;
@@ -84,6 +90,14 @@ class WebViewImpl : public mojom::WebView,
const CanNavigateFrameCallback& callback) override;
void DidStartNavigation(Frame* frame) override;
void DidCommitProvisionalLoad(Frame* frame) override;
+ void DidDestroyFrame(Frame* frame) override;
+ void OnFindInFrameCountUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t count,
+ bool final_update) override;
+ void OnFindInPageSelectionUpdated(int32_t request_id,
+ Frame* frame,
+ int32_t active_match_ordinal) override;
// Overridden from FrameDevToolsAgent::Delegate:
void HandlePageNavigateRequest(const GURL& url) override;
@@ -92,6 +106,10 @@ class WebViewImpl : public mojom::WebView,
void OnNavigate(mojo::URLRequestPtr request) override;
void OnDidNavigate() override;
+ // Overridden from FindControllerDelegate:
+ std::deque<Frame*> GetAllFrames() override;
+ mojom::WebViewClient* GetWebViewClient() override;
+
mojo::ApplicationImpl* app_;
mojom::WebViewClientPtr client_;
mojo::StrongBinding<WebView> binding_;
@@ -108,6 +126,8 @@ class WebViewImpl : public mojom::WebView,
NavigationController navigation_controller_;
+ FindController find_controller_;
+
DISALLOW_COPY_AND_ASSIGN(WebViewImpl);
};