123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- // Copyright 2019 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.
- #import <UIKit/UIKit.h>
- #import <WebKit/WebKit.h>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/run_loop.h"
- #import "base/test/ios/wait_util.h"
- #import "ios/web/find_in_page/find_in_page_constants.h"
- #import "ios/web/find_in_page/find_in_page_java_script_feature.h"
- #import "ios/web/js_messaging/java_script_feature_manager.h"
- #include "ios/web/js_messaging/web_frame_impl.h"
- #import "ios/web/public/js_messaging/web_frame.h"
- #import "ios/web/public/js_messaging/web_frames_manager.h"
- #import "ios/web/public/test/js_test_util.h"
- #import "ios/web/public/test/web_test_with_web_state.h"
- #import "ios/web/public/ui/crw_web_view_proxy.h"
- #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
- #import "ios/web/public/web_state.h"
- #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
- #include "testing/gtest_mac.h"
- #if !defined(__has_feature) || !__has_feature(objc_arc)
- #error "This file requires ARC support."
- #endif
- using base::test::ios::kWaitForJSCompletionTimeout;
- using base::test::ios::kWaitForPageLoadTimeout;
- using base::test::ios::WaitUntilConditionOrTimeout;
- namespace {
- // Find strings.
- const char kFindStringFoo[] = "foo";
- const char kFindString12345[] = "12345";
- // Pump search timeout in milliseconds.
- const double kPumpSearchTimeout = 100.0;
- } // namespace
- namespace web {
- // Calls FindInPage Javascript handlers and checks that return values are
- // correct.
- class FindInPageJsTest : public WebTestWithWebState {
- protected:
- void SetUp() override {
- WebTestWithWebState::SetUp();
- WKWebViewConfigurationProvider& configuration_provider =
- WKWebViewConfigurationProvider::FromBrowserState(GetBrowserState());
- // Force the creation of the content worlds.
- configuration_provider.GetWebViewConfiguration();
- content_world_ =
- JavaScriptFeatureManager::FromBrowserState(GetBrowserState())
- ->GetContentWorldForFeature(
- FindInPageJavaScriptFeature::GetInstance());
- }
- bool WaitForWebFramesCount(unsigned long web_frames_count) {
- return WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return all_web_frames().size() == web_frames_count;
- });
- }
- // Returns all web frames for |web_state()|.
- std::set<WebFrameImpl*> all_web_frames() {
- std::set<WebFrameImpl*> frames;
- for (WebFrame* frame :
- web_state()->GetWebFramesManager()->GetAllWebFrames()) {
- frames.insert(static_cast<WebFrameImpl*>(frame));
- }
- return frames;
- }
- // Returns main frame for |web_state_|.
- WebFrameInternal* main_web_frame() {
- WebFrame* main_frame =
- web_state()->GetWebFramesManager()->GetMainWebFrame();
- return main_frame->GetWebFrameInternal();
- }
- JavaScriptContentWorld* content_world_;
- };
- // Tests that FindInPage searches in main frame containing a match and responds
- // with 1 match.
- TEST_F(FindInPageJsTest, FindText) {
- ASSERT_TRUE(LoadHtml("<span>foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage searches in main frame for text that exists but is
- // hidden and responds with 0 matches.
- TEST_F(FindInPageJsTest, FindTextNoResults) {
- ASSERT_TRUE(LoadHtml("<span style='display:none'>foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(0.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage doesn't search in noscript elements.
- TEST_F(FindInPageJsTest, FindTextIgnoresNoscript) {
- ASSERT_TRUE(LoadHtml("<body><noscript>foo</noscript></body>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(0.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage searches in child iframe and asserts that a result was
- // found.
- TEST_F(FindInPageJsTest, FindIFrameText) {
- ASSERT_TRUE(WebTestWithWebState::LoadHtml(
- "<iframe "
- "srcdoc='<html><body><span>foo</span></body></html>'></iframe>"));
- ASSERT_TRUE(WaitForWebFramesCount(2));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- std::set<WebFrameImpl*> all_frames = all_web_frames();
- __block bool message_received = false;
- WebFrameInternal* child_frame = nullptr;
- for (auto* frame : all_frames) {
- if (frame->IsMainFrame()) {
- continue;
- }
- child_frame = frame->GetWebFrameInternal();
- }
- ASSERT_TRUE(child_frame);
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- child_frame->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage works when searching for white space.
- TEST_F(FindInPageJsTest, FindWhiteSpace) {
- ASSERT_TRUE(LoadHtml("<span> </span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(" "));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage works when match results cover multiple HTML Nodes.
- TEST_F(FindInPageJsTest, FindAcrossMultipleNodes) {
- ASSERT_TRUE(
- LoadHtml("<p>xx1<span>2</span>3<a>4512345xxx12</a>34<a>5xxx12345xx</p>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindString12345));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(4.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that a FindInPage match can be highlighted and the correct
- // accessibility string is returned.
- TEST_F(FindInPageJsTest, FindHighlightMatch) {
- ASSERT_TRUE(LoadHtml("<span>some foo match</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- __block bool highlight_done = false;
- __block std::string context_string;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- highlight_done = true;
- context_string =
- result->FindKey(kSelectAndScrollResultContextString)->GetString();
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return highlight_done;
- }));
- EXPECT_NSEQ(@1,
- ExecuteJavaScript(
- @"document.getElementsByClassName('find_selected').length"));
- EXPECT_EQ("some foo match", context_string);
- }
- // Tests that a FindInPage match can be highlighted and that a previous
- // highlight is removed when another match is highlighted.
- TEST_F(FindInPageJsTest, FindHighlightSeparateMatches) {
- ASSERT_TRUE(LoadHtml("<span>foo foo match</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(2.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- __block bool highlight_done = false;
- __block std::string context_string;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- highlight_done = true;
- context_string =
- result->FindKey(kSelectAndScrollResultContextString)->GetString();
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return highlight_done;
- }));
- EXPECT_EQ("foo ", context_string);
- EXPECT_NSEQ(@1,
- ExecuteJavaScript(
- @"document.getElementsByClassName('find_selected').length"));
- highlight_done = false;
- std::vector<base::Value> highlight_second_params;
- highlight_second_params.push_back(base::Value(1));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_second_params,
- content_world_, base::BindOnce(^(const base::Value* result) {
- highlight_done = true;
- context_string =
- result->FindKey(kSelectAndScrollResultContextString)->GetString();
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return highlight_done;
- }));
- EXPECT_EQ(" foo match", context_string);
- id inner_html = ExecuteJavaScript(@"document.body.innerHTML");
- ASSERT_TRUE([inner_html isKindOfClass:[NSString class]]);
- EXPECT_TRUE([inner_html
- containsString:@"<chrome_find class=\"find_in_page\">foo</chrome_find> "
- @"<chrome_find class=\"find_in_page "
- @"find_selected\">foo</chrome_find>"]);
- EXPECT_TRUE(
- [inner_html containsString:@"find_selected{background-color:#ff9632"]);
- }
- // Tests that FindInPage does not highlight any matches given an invalid index.
- TEST_F(FindInPageJsTest, FindHighlightMatchAtInvalidIndex) {
- ASSERT_TRUE(LoadHtml("<span>invalid </span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_TRUE(count == 0.0);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- __block bool highlight_done = false;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- highlight_done = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return highlight_done;
- }));
- EXPECT_NSEQ(@0,
- ExecuteJavaScript(
- @"document.getElementsByClassName('find_selected').length"));
- }
- // Tests that FindInPage works when searching for strings with non-ascii
- // characters.
- TEST_F(FindInPageJsTest, SearchForNonAscii) {
- ASSERT_TRUE(LoadHtml("<span>école francais</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value("école"));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- }
- // Tests that FindInPage scrolls page to bring selected match into view.
- TEST_F(FindInPageJsTest, CheckFindInPageScrollsToMatch) {
- // Set frame so that offset can be predictable across devices.
- web_state()->GetView().frame = CGRectMake(0, 0, 300, 200);
- // Create HTML with div of height 4000px followed by a span below with
- // searchable text in order to ensure that the text begins outside of screen
- // on all devices.
- ASSERT_TRUE(
- LoadHtml("<div style=\"height: 4000px;\"></div><span>foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value("foo"));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- ASSERT_EQ(1.0, result->GetDouble());
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- __block bool highlight_done = false;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- highlight_done = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return highlight_done;
- }));
- // Check that page has scrolled to the match.
- __block CGFloat top_scroll_after_select = 0.0;
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- top_scroll_after_select =
- web_state()->GetWebViewProxy().scrollViewProxy.contentOffset.y;
- return top_scroll_after_select > 0;
- }));
- // Scroll offset should either be 1035.333 for most iPhone and 1035.5 for iPad
- // and 5S.
- EXPECT_NEAR(top_scroll_after_select, 1035, 1.0);
- }
- // Tests that FindInPage is able to clear CSS and match highlighting.
- TEST_F(FindInPageJsTest, StopFindInPage) {
- ASSERT_TRUE(LoadHtml("<span>foo foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- // Do a search to ensure match highlighting is cleared properly.
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value("foo"));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return message_received;
- }));
- message_received = false;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return message_received;
- }));
- message_received = false;
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageStop, std::vector<base::Value>(), content_world_,
- base::BindOnce(^(const base::Value* result) {
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return message_received;
- }));
- id inner_html = ExecuteJavaScript(@"document.body.innerHTML");
- ASSERT_TRUE([inner_html isKindOfClass:[NSString class]]);
- EXPECT_FALSE([inner_html containsString:@"find_selected"]);
- EXPECT_FALSE([inner_html containsString:@"find_in_page"]);
- EXPECT_FALSE([inner_html containsString:@"chrome_find"]);
- }
- // Tests that FindInPage only selects the visible match when there is also a
- // hidden match.
- TEST_F(FindInPageJsTest, HiddenMatch) {
- ASSERT_TRUE(
- LoadHtml("<span style='display:none'>foo</span><span>foo bar</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- message_received = false;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return message_received;
- }));
- id inner_html = ExecuteJavaScript(@"document.body.innerHTML");
- ASSERT_TRUE([inner_html isKindOfClass:[NSString class]]);
- NSRange visible_match =
- [inner_html rangeOfString:@"find_in_page find_selected"];
- NSRange hidden_match = [inner_html rangeOfString:@"find_in_page"];
- // Assert that the selected match comes after the first match in the DOM since
- // it is expected the hidden match is skipped.
- EXPECT_GT(visible_match.location, hidden_match.location);
- }
- // Tests that FindInPage responds with an updated match count when a once
- // hidden match becomes visible after a search finishes.
- TEST_F(FindInPageJsTest, HiddenMatchBecomesVisible) {
- ASSERT_TRUE(LoadHtml("<span>foo</span><span id=\"hidden_match\" "
- "style='display:none'>foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- ASSERT_EQ(1.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- ExecuteJavaScript(
- @"document.getElementById('hidden_match').removeAttribute('style')");
- message_received = false;
- std::vector<base::Value> highlight_params;
- highlight_params.push_back(base::Value(0));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, highlight_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_dict());
- const base::Value* count =
- result->FindKey(kSelectAndScrollResultMatches);
- ASSERT_TRUE(count->is_double());
- ASSERT_EQ(2.0, count->GetDouble());
- const base::Value* index = result->FindKey(kSelectAndScrollResultIndex);
- ASSERT_TRUE(index->is_double());
- ASSERT_EQ(0.0, index->GetDouble());
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return message_received;
- }));
- }
- // Tests that FindInPage highlights the next visible match when attempting to
- // select a match that was once visible but is no longer.
- TEST_F(FindInPageJsTest, MatchBecomesInvisible) {
- ASSERT_TRUE(LoadHtml(
- "<span>foo foo </span> <span id=\"matches_to_hide\">foo foo</span>"));
- ASSERT_TRUE(WaitForWebFramesCount(1));
- const base::TimeDelta kCallJavascriptFunctionTimeout =
- base::Seconds(kWaitForJSCompletionTimeout);
- __block bool message_received = false;
- std::vector<base::Value> params;
- params.push_back(base::Value(kFindStringFoo));
- params.push_back(base::Value(kPumpSearchTimeout));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSearch, params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_double());
- double count = result->GetDouble();
- EXPECT_EQ(4.0, count);
- message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- return message_received;
- }));
- __block bool select_last_match_message_received = false;
- std::vector<base::Value> select_params;
- select_params.push_back(base::Value(3));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, select_params, content_world_,
- base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_dict());
- const base::Value* index = result->FindKey(kSelectAndScrollResultIndex);
- ASSERT_TRUE(index->is_double());
- EXPECT_EQ(3.0, index->GetDouble());
- select_last_match_message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return select_last_match_message_received;
- }));
- ExecuteJavaScript(
- @"document.getElementById('matches_to_hide').style.display = \"none\";");
- __block bool select_third_match_message_received = false;
- std::vector<base::Value> select_third_match_params;
- select_third_match_params.push_back(base::Value(2));
- main_web_frame()->CallJavaScriptFunctionInContentWorld(
- kFindInPageSelectAndScrollToMatch, select_third_match_params,
- content_world_, base::BindOnce(^(const base::Value* result) {
- ASSERT_TRUE(result);
- ASSERT_TRUE(result->is_dict());
- const base::Value* index = result->FindKey(kSelectAndScrollResultIndex);
- ASSERT_TRUE(index->is_double());
- // Since there are only two visible matches now and this
- // kFindInPageSelectAndScrollToMatch call is asking Find in Page to
- // traverse to a previous match, Find in Page should look for the next
- // previous visible match. This happens to be the 2nd match.
- EXPECT_EQ(1.0, index->GetDouble());
- select_third_match_message_received = true;
- }),
- kCallJavascriptFunctionTimeout);
- ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
- base::RunLoop().RunUntilIdle();
- return select_third_match_message_received;
- }));
- }
- } // namespace web
|