| Index: content/browser/find_request_manager_browsertest.cc
|
| diff --git a/content/browser/find_request_manager_browsertest.cc b/content/browser/find_request_manager_browsertest.cc
|
| index c8ac858f4bdb5e3cd4a7a682b593841757777266..0ce93a6d6f02eb0a3726e9f356c9c14c4deb3b3a 100644
|
| --- a/content/browser/find_request_manager_browsertest.cc
|
| +++ b/content/browser/find_request_manager_browsertest.cc
|
| @@ -12,6 +12,7 @@
|
| #include "content/public/test/test_navigation_observer.h"
|
| #include "content/public/test/test_utils.h"
|
| #include "content/shell/browser/shell.h"
|
| +#include "content/test/content_browser_test_utils_internal.h"
|
| #include "net/dns/mock_host_resolver.h"
|
| #include "third_party/WebKit/public/web/WebFindOptions.h"
|
|
|
| @@ -52,6 +53,31 @@ class TestWebContentsDelegate : public WebContentsDelegate {
|
| return current_results_;
|
| }
|
|
|
| +#if defined(OS_ANDROID)
|
| + // Waits for the next find reply. This is useful for waiting for a single
|
| + // match to be activated, which results in a single find reply (without a
|
| + // unique request ID).
|
| + void WaitForNextReply() {
|
| + waiting_request_id_ = 0;
|
| + find_message_loop_runner_ = new content::MessageLoopRunner;
|
| + find_message_loop_runner_->Run();
|
| + }
|
| +
|
| + // Waits for all of the find match rects to be received.
|
| + void WaitForMatchRects() {
|
| + match_rects_message_loop_runner_ = new content::MessageLoopRunner;
|
| + match_rects_message_loop_runner_->Run();
|
| + }
|
| +
|
| + const std::vector<gfx::RectF>& find_match_rects() const {
|
| + return find_match_rects_;
|
| + }
|
| +
|
| + const gfx::RectF& active_match_rect() const {
|
| + return active_match_rect_;
|
| + }
|
| +#endif
|
| +
|
| private:
|
| // WebContentsDelegate override.
|
| void FindReply(WebContents* web_contents,
|
| @@ -78,6 +104,25 @@ class TestWebContentsDelegate : public WebContentsDelegate {
|
| }
|
| }
|
|
|
| +#if defined(OS_ANDROID)
|
| + void FindMatchRectsReply(WebContents* web_contents,
|
| + int version,
|
| + const std::vector<gfx::RectF>& rects,
|
| + const gfx::RectF& active_rect) override {
|
| + // Update the current rects.
|
| + find_match_rects_ = rects;
|
| + active_match_rect_ = active_rect;
|
| +
|
| + // If we are waiting for match rects, stop waiting.
|
| + if (match_rects_message_loop_runner_.get())
|
| + match_rects_message_loop_runner_->Quit();
|
| + }
|
| +
|
| + std::vector<gfx::RectF> find_match_rects_;
|
| +
|
| + gfx::RectF active_match_rect_;
|
| +#endif
|
| +
|
| // The latest known results from the current find request.
|
| FindResults current_results_;
|
|
|
| @@ -89,11 +134,13 @@ class TestWebContentsDelegate : public WebContentsDelegate {
|
| int waiting_request_id_;
|
|
|
| scoped_refptr<content::MessageLoopRunner> find_message_loop_runner_;
|
| + scoped_refptr<content::MessageLoopRunner> match_rects_message_loop_runner_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TestWebContentsDelegate);
|
| };
|
|
|
| -class FindRequestManagerTest : public ContentBrowserTest {
|
| +class FindRequestManagerTest : public ContentBrowserTest,
|
| + public testing::WithParamInterface<bool> {
|
| public:
|
| FindRequestManagerTest()
|
| : normal_delegate_(nullptr),
|
| @@ -114,18 +161,49 @@ class FindRequestManagerTest : public ContentBrowserTest {
|
| contents()->SetDelegate(normal_delegate_);
|
| }
|
|
|
| +#if !defined(OS_ANDROID)
|
| void SetUpCommandLine(base::CommandLine* command_line) override {
|
| IsolateAllSitesForTesting(command_line);
|
| }
|
| +#endif
|
|
|
| protected:
|
| - // Navigate to |url| and wait for it to finish loading.
|
| + // Navigates to |url| and waits for it to finish loading.
|
| void LoadAndWait(const std::string& url) {
|
| TestNavigationObserver navigation_observer(contents());
|
| NavigateToURL(shell(), embedded_test_server()->GetURL("a.com", url));
|
| EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
|
| }
|
|
|
| + // Loads a multi-frame page. The page will have a full binary frame tree of
|
| + // height |height|. If |cross_process| is true, child frames will be loaded
|
| + // cross-process.
|
| + void LoadMultiFramePage(int height, bool cross_process) {
|
| + LoadAndWait("/find_in_page_multi_frame.html");
|
| +
|
| + FrameTreeNode* root =
|
| + static_cast<WebContentsImpl*>(shell()->web_contents())->
|
| + GetFrameTree()->root();
|
| +
|
| + LoadMultiFramePageChildFrames(height, cross_process, root);
|
| + }
|
| +
|
| + // Reloads the child frame cross-process.
|
| + void MakeChildFrameCrossProcess() {
|
| + FrameTreeNode* root =
|
| + static_cast<WebContentsImpl*>(shell()->web_contents())->
|
| + GetFrameTree()->root();
|
| +
|
| + TestNavigationObserver observer(shell()->web_contents());
|
| +
|
| + FrameTreeNode* child = root->child_at(0);
|
| + GURL url(embedded_test_server()->GetURL("b.com",
|
| + child->current_url().path()));
|
| + NavigateFrameToURL(child, url);
|
| + EXPECT_EQ(url, observer.last_navigation_url());
|
| + EXPECT_TRUE(observer.last_navigation_succeeded());
|
| + }
|
| +
|
| void Find(const std::string& search_text,
|
| const blink::WebFindOptions& options) {
|
| contents()->Find(++last_request_id_,
|
| @@ -150,6 +228,33 @@ class FindRequestManagerTest : public ContentBrowserTest {
|
| }
|
|
|
| private:
|
| + // Helper function for LoadMultiFramePage. Loads child frames until the frame
|
| + // tree rooted at |root| is a full binary tree of height |height|.
|
| + void LoadMultiFramePageChildFrames(int height,
|
| + bool cross_process,
|
| + FrameTreeNode* root) {
|
| + if (height == 0)
|
| + return;
|
| +
|
| + std::string hostname = root->current_origin().host();
|
| + if (cross_process)
|
| + hostname.insert(0, 1, 'a');
|
| + GURL url(embedded_test_server()->GetURL(hostname,
|
| + "/find_in_page_multi_frame.html"));
|
| +
|
| + TestNavigationObserver observer(shell()->web_contents());
|
| +
|
| + FrameTreeNode* child = root->child_at(0);
|
| + NavigateFrameToURL(child, url);
|
| + EXPECT_TRUE(observer.last_navigation_succeeded());
|
| + LoadMultiFramePageChildFrames(height - 1, cross_process, child);
|
| +
|
| + child = root->child_at(1);
|
| + NavigateFrameToURL(child, url);
|
| + EXPECT_TRUE(observer.last_navigation_succeeded());
|
| + LoadMultiFramePageChildFrames(height - 1, cross_process, child);
|
| + }
|
| +
|
| TestWebContentsDelegate test_delegate_;
|
| WebContentsDelegate* normal_delegate_;
|
|
|
| @@ -159,14 +264,43 @@ class FindRequestManagerTest : public ContentBrowserTest {
|
| DISALLOW_COPY_AND_ASSIGN(FindRequestManagerTest);
|
| };
|
|
|
| -// TODO(paulmeyer): These tests currently fail on the linux_android_rel_ng
|
| -// trybot. Remove this guard once that problem is figured out.
|
| -#if !defined(OS_ANDROID)
|
| -
|
| -// Test basic find-in-page functionality (such as searching forward and
|
| +// Frames are made cross-process when the test param is set to
|
| +// true. Cross-process frames are not used on android.
|
| +#if defined(OS_ANDROID)
|
| +INSTANTIATE_TEST_CASE_P(
|
| + FindRequestManagerTests, FindRequestManagerTest, testing::Values(false));
|
| +#else
|
| +INSTANTIATE_TEST_CASE_P(
|
| + FindRequestManagerTests, FindRequestManagerTest, testing::Bool());
|
| +#endif
|
| +
|
| +// TODO(crbug.com/615291): These tests sometimes fail on the
|
| +// linux_android_rel_ng trybot.
|
| +#if defined(OS_ANDROID) && defined(NDEBUG)
|
| +#define MAYBE_Basic DISABLED_Basic
|
| +#define MAYBE_CharacterByCharacter DISABLED_CharacterByCharacter
|
| +#define MAYBE_RapidFire DISABLED_RapidFire
|
| +#define MAYBE_RemoveFrame DISABLED_RemoveFrame
|
| +#define MAYBE_HiddenFrame DISABLED_HiddenFrame
|
| +#define MAYBE_FindMatchRects DISABLED_FindMatchRects
|
| +#define MAYBE_ActivateNearestFindMatch DISABLED_ActivateNearestFindMatch
|
| +#else
|
| +#define MAYBE_Basic Basic
|
| +#define MAYBE_CharacterByCharacter CharacterByCharacter
|
| +#define MAYBE_RapidFire RapidFire
|
| +#define MAYBE_RemoveFrame RemoveFrame
|
| +#define MAYBE_HiddenFrame HiddenFrame
|
| +#define MAYBE_FindMatchRects FindMatchRects
|
| +#define MAYBE_ActivateNearestFindMatch ActivateNearestFindMatch
|
| +#endif
|
| +
|
| +
|
| +// Tests basic find-in-page functionality (such as searching forward and
|
| // backward) and check for correct results at each step.
|
| -IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, Basic) {
|
| +IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_Basic) {
|
| LoadAndWait("/find_in_page.html");
|
| + if (GetParam())
|
| + MakeChildFrameCrossProcess();
|
|
|
| blink::WebFindOptions options;
|
| Find("result", options);
|
| @@ -202,8 +336,10 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, Basic) {
|
|
|
| // Tests searching for a word character-by-character, as would typically be done
|
| // by a user typing into the find bar.
|
| -IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, CharacterByCharacter) {
|
| +IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_CharacterByCharacter) {
|
| LoadAndWait("/find_in_page.html");
|
| + if (GetParam())
|
| + MakeChildFrameCrossProcess();
|
|
|
| blink::WebFindOptions default_options;
|
| Find("r", default_options);
|
| @@ -220,9 +356,11 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, CharacterByCharacter) {
|
| EXPECT_EQ(1, results.active_match_ordinal);
|
| }
|
|
|
| -// Test sending a large number of find requests subsequently.
|
| -IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, RapidFire) {
|
| +// Tests sending a large number of find requests subsequently.
|
| +IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_RapidFire) {
|
| LoadAndWait("/find_in_page.html");
|
| + if (GetParam())
|
| + MakeChildFrameCrossProcess();
|
|
|
| blink::WebFindOptions options;
|
| Find("result", options);
|
| @@ -239,6 +377,165 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, RapidFire) {
|
| results.active_match_ordinal);
|
| }
|
|
|
| -#endif // OS_ANDROID
|
| +// Tests removing a frame during a find session.
|
| +IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_RemoveFrame) {
|
| + LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
|
| +
|
| + blink::WebFindOptions options;
|
| + Find("result", options);
|
| + options.findNext = true;
|
| + options.forward = false;
|
| + Find("result", options);
|
| + Find("result", options);
|
| + Find("result", options);
|
| + Find("result", options);
|
| + Find("result", options);
|
| + WaitForFinalReply();
|
| +
|
| + FindResults results = delegate()->GetFindResults();
|
| + EXPECT_EQ(last_request_id(), results.request_id);
|
| + EXPECT_EQ(21, results.number_of_matches);
|
| + EXPECT_EQ(17, results.active_match_ordinal);
|
| +
|
| + // Remove a frame.
|
| + FrameTreeNode* root =
|
| + static_cast<WebContentsImpl*>(shell()->web_contents())->
|
| + GetFrameTree()->root();
|
| + root->RemoveChild(root->child_at(0));
|
| +
|
| + // The number of matches and active match ordinal should update automatically
|
| + // to exclude the matches from the removed frame.
|
| + results = delegate()->GetFindResults();
|
| + EXPECT_EQ(last_request_id(), results.request_id);
|
| + EXPECT_EQ(12, results.number_of_matches);
|
| + EXPECT_EQ(8, results.active_match_ordinal);
|
| +
|
| + // TODO(paulemeyer): Once adding frames mid-session is handled, test that too.
|
| +}
|
| +
|
| +// Tests Searching in a hidden frame. Matches in the hidden frame should be
|
| +// ignored.
|
| +IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_HiddenFrame) {
|
| + LoadAndWait("/find_in_hidden_frame.html");
|
| +
|
| + blink::WebFindOptions default_options;
|
| + Find("hello", default_options);
|
| + WaitForFinalReply();
|
| + FindResults results = delegate()->GetFindResults();
|
| +
|
| + EXPECT_EQ(last_request_id(), results.request_id);
|
| + EXPECT_EQ(1, results.number_of_matches);
|
| + EXPECT_EQ(1, results.active_match_ordinal);
|
| +}
|
| +
|
| +#if defined(OS_ANDROID)
|
| +// Tests requesting find match rects.
|
| +IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindMatchRects) {
|
| + LoadAndWait("/find_in_page.html");
|
| +
|
| + blink::WebFindOptions default_options;
|
| + Find("result", default_options);
|
| + WaitForFinalReply();
|
| + EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
|
| +
|
| + // Request the find match rects.
|
| + contents()->RequestFindMatchRects(-1);
|
| + delegate()->WaitForMatchRects();
|
| + const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();
|
| +
|
| + // The first match should be active.
|
| + EXPECT_EQ(rects[0], delegate()->active_match_rect());
|
| +
|
| + // All results after the first two should be between them in find-in-page
|
| + // coordinates. This is because results 2 to 19 are inside an iframe located
|
| + // between results 0 and 1. This applies to the fixed div too.
|
| + EXPECT_LT(rects[0].y(), rects[1].y());
|
| + for (int i = 2; i < 19; ++i) {
|
| + EXPECT_LT(rects[0].y(), rects[i].y());
|
| + EXPECT_GT(rects[1].y(), rects[i].y());
|
| + }
|
| +
|
| + // Result 3 should be below results 2 and 4. This is caused by the CSS
|
| + // transform in the containing div. If the transform doesn't work then result
|
| + // 3 will be between results 2 and 4.
|
| + EXPECT_GT(rects[3].y(), rects[2].y());
|
| + EXPECT_GT(rects[3].y(), rects[4].y());
|
| +
|
| + // Results 6, 7, 8 and 9 should be one below the other in that same order. If
|
| + // overflow:scroll is not properly handled then result 8 would be below result
|
| + // 9 or result 7 above result 6 depending on the scroll.
|
| + EXPECT_LT(rects[6].y(), rects[7].y());
|
| + EXPECT_LT(rects[7].y(), rects[8].y());
|
| + EXPECT_LT(rects[8].y(), rects[9].y());
|
| +
|
| + // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are
|
| + // inside the table.
|
| + EXPECT_GT(rects[11].y(), rects[10].y());
|
| + EXPECT_GT(rects[12].y(), rects[10].y());
|
| + EXPECT_GT(rects[13].y(), rects[10].y());
|
| + EXPECT_GT(rects[14].y(), rects[10].y());
|
| + EXPECT_LT(rects[11].y(), rects[15].y());
|
| + EXPECT_LT(rects[12].y(), rects[15].y());
|
| + EXPECT_LT(rects[13].y(), rects[15].y());
|
| + EXPECT_LT(rects[14].y(), rects[15].y());
|
| +
|
| + // Result 11 should be above results 12, 13 and 14 as it's in the table
|
| + // header.
|
| + EXPECT_LT(rects[11].y(), rects[12].y());
|
| + EXPECT_LT(rects[11].y(), rects[13].y());
|
| + EXPECT_LT(rects[11].y(), rects[14].y());
|
| +
|
| + // Result 11 should also be right of results 12, 13 and 14 because of the
|
| + // colspan.
|
| + EXPECT_GT(rects[11].x(), rects[12].x());
|
| + EXPECT_GT(rects[11].x(), rects[13].x());
|
| + EXPECT_GT(rects[11].x(), rects[14].x());
|
| +
|
| + // Result 12 should be left of results 11, 13 and 14 in the table layout.
|
| + EXPECT_LT(rects[12].x(), rects[11].x());
|
| + EXPECT_LT(rects[12].x(), rects[13].x());
|
| + EXPECT_LT(rects[12].x(), rects[14].x());
|
| +
|
| + // Results 13, 12 and 14 should be one above the other in that order because
|
| + // of the rowspan and vertical-align: middle by default.
|
| + EXPECT_LT(rects[13].y(), rects[12].y());
|
| + EXPECT_LT(rects[12].y(), rects[14].y());
|
| +
|
| + // Result 16 should be below result 15.
|
| + EXPECT_GT(rects[15].y(), rects[14].y());
|
| +
|
| + // Result 18 should be normalized with respect to the position:relative div,
|
| + // and not it's immediate containing div. Consequently, result 18 should be
|
| + // above result 17.
|
| + EXPECT_GT(rects[17].y(), rects[18].y());
|
| +}
|
| +
|
| +// Tests activating the find match nearest to a given point.
|
| +IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_ActivateNearestFindMatch) {
|
| + LoadAndWait("/find_in_page.html");
|
| +
|
| + blink::WebFindOptions default_options;
|
| + Find("result", default_options);
|
| + WaitForFinalReply();
|
| + EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
|
| +
|
| + // Get the find match rects.
|
| + contents()->RequestFindMatchRects(-1);
|
| + delegate()->WaitForMatchRects();
|
| + const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();
|
| +
|
| + // Activate matches via points inside each of the find match rects, in an
|
| + // arbitrary order. Check that the correct match becomes active after each
|
| + // activation.
|
| + int order[19] =
|
| + {11, 13, 2, 0, 16, 5, 7, 10, 6, 1, 15, 14, 9, 17, 18, 3, 8, 12, 4};
|
| + for (int i = 0; i < 19; ++i) {
|
| + contents()->ActivateNearestFindResult(
|
| + rects[order[i]].CenterPoint().x(), rects[order[i]].CenterPoint().y());
|
| + delegate()->WaitForNextReply();
|
| + EXPECT_EQ(order[i] + 1, delegate()->GetFindResults().active_match_ordinal);
|
| + }
|
| +}
|
| +#endif // defined(OS_ANDROID)
|
|
|
| } // namespace content
|
|
|