diff options
Diffstat (limited to 'chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc')
-rw-r--r-- | chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc | 387 |
1 files changed, 101 insertions, 286 deletions
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc index 0bce668ea90..aed1001cd56 100644 --- a/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc +++ b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc @@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/callback_forward.h" #include "base/callback_helpers.h" #include "base/containers/checked_range.h" #include "base/location.h" @@ -57,11 +56,10 @@ #include "components/autofill_assistant/browser/user_model.h" #include "components/autofill_assistant/browser/web/element.h" #include "components/autofill_assistant/browser/web/element_action_util.h" -#include "components/autofill_assistant/browser/web/element_finder.h" +#include "components/autofill_assistant/browser/web/element_finder_result.h" +#include "components/autofill_assistant/browser/web/element_finder_result_type.h" #include "components/autofill_assistant/browser/web/element_store.h" -#include "components/autofill_assistant/content/common/autofill_assistant_agent.mojom.h" -#include "components/autofill_assistant/content/common/autofill_assistant_types.mojom.h" -#include "components/autofill_assistant/content/common/node_data.h" +#include "components/autofill_assistant/browser/web/mock_autofill_assistant_agent.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -69,12 +67,8 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" -#include "mojo/public/cpp/bindings/associated_receiver_set.h" -#include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" -#include "third_party/blink/public/common/switches.h" #include "url/gurl.h" #include "url/url_constants.h" @@ -86,34 +80,8 @@ using ::testing::_; using ::testing::AnyOf; using ::testing::IsEmpty; using ::testing::Return; -using ::testing::SaveArg; using ::testing::WithArgs; -class MockAutofillAssistantAgent : public mojom::AutofillAssistantAgent { - public: - MockAutofillAssistantAgent() = default; - ~MockAutofillAssistantAgent() override = default; - - void BindPendingReceiver(mojo::ScopedInterfaceEndpointHandle handle) { - receivers_.Add( - this, mojo::PendingAssociatedReceiver<mojom::AutofillAssistantAgent>( - std::move(handle))); - } - - MOCK_METHOD(void, - GetSemanticNodes, - (int32_t role, - int32_t objective, - bool ignore_objective, - base::TimeDelta model_timeout, - base::OnceCallback<void(mojom::NodeDataStatus, - const std::vector<NodeData>&)> callback), - (override)); - - private: - mojo::AssociatedReceiverSet<mojom::AutofillAssistantAgent> receivers_; -}; - } // namespace class WebControllerBrowserTest : public autofill_assistant::BaseBrowserTest, @@ -129,22 +97,13 @@ class WebControllerBrowserTest : public autofill_assistant::BaseBrowserTest, void SetUpOnMainThread() override { BaseBrowserTest::SetUpOnMainThread(); - // Register the same agent on all frames, such that the callback can be - // mocked. - shell()->web_contents()->GetMainFrame()->ForEachRenderFrameHost( - base::BindLambdaForTesting([this](content::RenderFrameHost* host) { - host->GetRemoteAssociatedInterfaces()->OverrideBinderForTesting( - mojom::AutofillAssistantAgent::Name_, - base::BindRepeating( - &MockAutofillAssistantAgent::BindPendingReceiver, - base::Unretained(&autofill_assistant_agent_))); - })); + MockAutofillAssistantAgent::RegisterForAllFrames( + shell()->web_contents(), &autofill_assistant_agent_); - annotate_dom_model_service_ = std::make_unique<AnnotateDomModelService>( - /* opt_guide= */ nullptr, /* background_task_runner= */ nullptr); web_controller_ = WebController::CreateForWebContents( shell()->web_contents(), &user_data_, &log_info_, - annotate_dom_model_service_.get(), /*enable_full_stack_traces= */ true); + /* annotate_dom_model_service= */ nullptr, + /*enable_full_stack_traces= */ true); Observe(shell()->web_contents()); } @@ -601,11 +560,11 @@ class WebControllerBrowserTest : public autofill_assistant::BaseBrowserTest, void CheckFindElementResult(const ElementFinderResult& result, bool is_main_frame) { if (is_main_frame) { - EXPECT_EQ(shell()->web_contents()->GetMainFrame(), + EXPECT_EQ(shell()->web_contents()->GetPrimaryMainFrame(), result.render_frame_host()); EXPECT_EQ(result.frame_stack().size(), 0u); } else { - EXPECT_NE(shell()->web_contents()->GetMainFrame(), + EXPECT_NE(shell()->web_contents()->GetPrimaryMainFrame(), result.render_frame_host()); EXPECT_GE(result.frame_stack().size(), 1u); } @@ -983,38 +942,21 @@ document.getElementById("overlay_in_frame").style.visibility='hidden'; return ClientStatus(captured_processed_actions[0].status()); } - int GetBackendNodeId(Selector selector, ClientStatus* status_out) { - std::unique_ptr<ElementFinderResult> element_result; - int backend_node_id = -1; - - base::RunLoop run_loop_1; - web_controller_->FindElement( - selector, true, - base::BindLambdaForTesting( - [&](const ClientStatus& status, - std::unique_ptr<ElementFinderResult> result) { - element_result = std::move(result); - *status_out = status; - run_loop_1.Quit(); - })); - run_loop_1.Run(); - if (!status_out->ok()) { - return backend_node_id; - } + ClientStatus GetBackendNodeId(const ElementFinderResult& element, + int* backend_node_id) { + ClientStatus result_status; - // Second part in sequence, lookup backend node id. - base::RunLoop run_loop_2; + base::RunLoop run_loop; web_controller_->GetBackendNodeId( - *element_result, + element, base::BindLambdaForTesting([&](const ClientStatus& status, int id) { - *status_out = status; - backend_node_id = id; - run_loop_2.Quit(); + result_status = status; + *backend_node_id = id; + run_loop.Quit(); })); - run_loop_2.Run(); + run_loop.Run(); - log_info_.Clear(); - return backend_node_id; + return result_status; } protected: @@ -1023,7 +965,6 @@ document.getElementById("overlay_in_frame").style.visibility='hidden'; UserModel user_model_; ProcessedActionStatusDetailsProto log_info_; MockAutofillAssistantAgent autofill_assistant_agent_; - std::unique_ptr<AnnotateDomModelService> annotate_dom_model_service_; }; IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ElementExistenceCheck) { @@ -2761,7 +2702,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, // This makes the devtools action fail. ElementFinderResult element; element.SetNodeFrameId("doesnotexist"); - element.SetRenderFrameHost(web_contents()->GetMainFrame()); + element.SetRenderFrameHost(web_contents()->GetPrimaryMainFrame()); EXPECT_EQ(ELEMENT_POSITION_NOT_FOUND, WaitUntilElementIsStable(element, 10, base::Milliseconds(100)) @@ -3151,46 +3092,6 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, EXPECT_EQ(status.proto_status(), ACTION_APPLIED); } -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, WaitForDomForSemanticElement) { - // This element is unique. - SelectorProto baseline_selector = ToSelectorProto("#select"); - - ClientStatus element_status; - int backend_node_id = - GetBackendNodeId(Selector(baseline_selector), &element_status); - EXPECT_TRUE(element_status.ok()); - - NodeData node_data; - node_data.backend_node_id = backend_node_id; - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - // Capture any other frames. - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); - - ActionProto action_proto; - auto* wait_for_dom = action_proto.mutable_wait_for_dom(); - auto* condition = wait_for_dom->mutable_wait_condition(); - condition->mutable_client_id()->set_identifier("e"); - condition->set_require_unique_element(true); - auto* semantic_information = - condition->mutable_match()->mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - - base::MockCallback<base::OnceCallback<void(ScriptExecutor*)>> - run_expectations; - EXPECT_CALL(run_expectations, Run(_)) - .WillOnce([](ScriptExecutor* script_executor) { - EXPECT_TRUE(script_executor->GetElementStore()->HasElement("e")); - }); - ClientStatus status = RunWaitForDom(action_proto, /* use_observers= */ false, - run_expectations.Get()); - EXPECT_EQ(status.proto_status(), ACTION_APPLIED); -} - IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, FindElementError) { ClientStatus element_status; ElementFinderResult element; @@ -3224,7 +3125,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, base::RunLoop button_run_loop; web_controller_->RunElementFinder( frame_element, Selector({"#shadowsection", "#shadowbutton"}), - ElementFinder::ResultType::kExactlyOneMatch, + ElementFinderResultType::kExactlyOneMatch, base::BindOnce(&WebControllerBrowserTest::OnFindElement, base::Unretained(this), button_run_loop.QuitClosure(), &button_status, &button_element)); @@ -3262,7 +3163,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, RunElementFinderFromOOPIF) { base::RunLoop button_run_loop; web_controller_->RunElementFinder( fake_frame_element, Selector({"#button"}), - ElementFinder::ResultType::kExactlyOneMatch, + ElementFinderResultType::kExactlyOneMatch, base::BindOnce(&WebControllerBrowserTest::OnFindElement, base::Unretained(this), button_run_loop.QuitClosure(), &button_status, &button_element)); @@ -3447,186 +3348,100 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ExecuteJSWithException) { testing::ElementsAre(18, 12, 10)); } -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, - ElementExistenceCheckWithSemanticModel) { - ClientStatus status; - int backend_node_id = GetBackendNodeId(Selector({"#button"}), &status); - EXPECT_TRUE(status.ok()); - - NodeData node_data; - node_data.backend_node_id = backend_node_id; - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - // Capture any other frames. - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); - - // We pretend that the button is the correct element. +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ParentFilter) { SelectorProto proto; - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - RunStrictElementCheck(Selector(proto), true); - - ASSERT_EQ(log_info_.element_finder_info().size(), 1); - const auto& result = - log_info_.element_finder_info(0).semantic_inference_result(); - ASSERT_EQ(1, result.predicted_elements().size()); - EXPECT_EQ(backend_node_id, result.predicted_elements(0).backend_node_id()); - EXPECT_THAT( - 1, result.predicted_elements(0).semantic_information().semantic_role()); - EXPECT_THAT(2, - result.predicted_elements(0).semantic_information().objective()); -} + proto.add_filters()->set_css_selector("#select option:checked"); + proto.add_filters()->mutable_parent(); -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, - ElementExistenceCheckWithSemanticModelOOPIF) { - ClientStatus status; - int backend_node_id = - GetBackendNodeId(Selector({"#iframeExternal", "#button"}), &status); - EXPECT_TRUE(status.ok()); + std::string element_tag; + EXPECT_EQ(ACTION_APPLIED, + GetElementTag(Selector(proto), &element_tag).proto_status()); + EXPECT_EQ("SELECT", element_tag); - NodeData node_data; - node_data.backend_node_id = backend_node_id; - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - // Capture any other frames. - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); - - // We pretend that the button is the correct element. - SelectorProto proto; - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - RunStrictElementCheck(Selector(proto), true); + SelectorProto failing_proto; + failing_proto.add_filters()->set_css_selector("body"); + failing_proto.add_filters()->mutable_parent(); // document + failing_proto.add_filters()->mutable_parent(); // Nothing - ASSERT_EQ(log_info_.element_finder_info().size(), 1); - const auto& result = - log_info_.element_finder_info(0).semantic_inference_result(); - ASSERT_EQ(1, result.predicted_elements().size()); - EXPECT_EQ(backend_node_id, result.predicted_elements(0).backend_node_id()); - EXPECT_THAT( - 1, result.predicted_elements(0).semantic_information().semantic_role()); - EXPECT_THAT(2, - result.predicted_elements(0).semantic_information().objective()); + ClientStatus failing_status; + ElementFinderResult ignored_element; + FindElement(Selector(failing_proto), &failing_status, &ignored_element); + EXPECT_EQ(ELEMENT_RESOLUTION_FAILED, failing_status.proto_status()); } -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, - ElementExistenceCheckWithSemanticModelNotFound) { - // All frames return an empty list as a result. - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillRepeatedly(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{})); +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, WebpageZoom) { + double initial_width = + content::EvalJs( + shell(), + R"(document.querySelector("#select").getBoundingClientRect().width)") + .ExtractDouble(); + EXPECT_GT(initial_width, 0); - SelectorProto proto; - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - FindElementExpectEmptyResult(Selector(proto)); -} + ClientStatus body_status; + ElementFinderResult body; + FindElement(Selector({"body"}), &body_status, &body); + EXPECT_EQ(ACTION_APPLIED, body_status.proto_status()); -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, - ElementExistenceCheckWithSemanticMultipleFound) { - SelectorProto proto; - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - - NodeData node_data; - node_data.backend_node_id = 5; - NodeData node_data_other; - node_data_other.backend_node_id = 13; - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data_other})) - // Capture any other frames. - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); - - // Two elements are found in different frames. - ClientStatus status; - FindElement(Selector(proto), &status, nullptr); - EXPECT_EQ(TOO_MANY_ELEMENTS, status.proto_status()); -} + ClientStatus zoom_status; + base::RunLoop zoom_run_loop; + web_controller_->ExecuteJS( + "this.style.webkitTransform = 'scale(2)'", body, + base::BindOnce(&WebControllerBrowserTest::OnClientStatus, + base::Unretained(this), zoom_run_loop.QuitClosure(), + &zoom_status)); + zoom_run_loop.Run(); + EXPECT_EQ(ACTION_APPLIED, zoom_status.proto_status()); -IN_PROC_BROWSER_TEST_F( - WebControllerBrowserTest, - ElementExistenceCheckWithSemanticModelUsesIgnoreObjective) { - NodeData node_data; - node_data.backend_node_id = 5; - EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, true, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); + double after_zoom_width = + content::EvalJs( + shell(), + R"(document.querySelector("#select").getBoundingClientRect().width)") + .ExtractDouble(); + EXPECT_NEAR(after_zoom_width, initial_width * 2, 1); - SelectorProto proto; - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - // All we want is this to be propagated to the GetSemanticNodes call as - // configured in the previous expectation. - semantic_information->set_ignore_objective(true); - - ClientStatus ignore_status; - FindElement(Selector(proto), &ignore_status, nullptr); - - // TODO(b/217160707): For now we expect the originally passed in semantic info - // to be logged instead of the objective inferred by the model. - ASSERT_EQ(log_info_.element_finder_info().size(), 1); - const auto& result = - log_info_.element_finder_info(0).semantic_inference_result(); - ASSERT_EQ(1, result.predicted_elements().size()); - EXPECT_EQ(5, result.predicted_elements(0).backend_node_id()); - EXPECT_THAT( - 1, result.predicted_elements(0).semantic_information().semantic_role()); - EXPECT_THAT(2, - result.predicted_elements(0).semantic_information().objective()); + ClientStatus reset_status; + base::RunLoop reset_run_loop; + web_controller_->ExecuteJS( + "this.style.webkitTransform = 'scale(1)'", body, + base::BindOnce(&WebControllerBrowserTest::OnClientStatus, + base::Unretained(this), reset_run_loop.QuitClosure(), + &reset_status)); + reset_run_loop.Run(); + EXPECT_EQ(ACTION_APPLIED, reset_status.proto_status()); + + double after_reset_width = + content::EvalJs( + shell(), + R"(document.querySelector("#select").getBoundingClientRect().width)") + .ExtractDouble(); + EXPECT_NEAR(after_reset_width, initial_width, 1); } -IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SemanticAndCssComparison) { - ClientStatus status; - int backend_node_id = GetBackendNodeId(Selector({"#button"}), &status); - EXPECT_TRUE(status.ok()); +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SetFieldValueThroughNative) { + ClientStatus element_status; + ElementFinderResult input; + FindElement(Selector({"#input1"}), &element_status, &input); + ASSERT_EQ(ACTION_APPLIED, element_status.proto_status()); - NodeData node_data; - node_data.backend_node_id = backend_node_id; + int backend_node_id; + ASSERT_EQ(ACTION_APPLIED, + GetBackendNodeId(input, &backend_node_id).proto_status()); + std::u16string expected_value = u"native"; EXPECT_CALL(autofill_assistant_agent_, - GetSemanticNodes(1, 2, false, base::Milliseconds(5000), _)) - .WillOnce(RunOnceCallback<4>(mojom::NodeDataStatus::kSuccess, - std::vector<NodeData>{node_data})) - // Capture any other frames. - .WillRepeatedly(RunOnceCallback<4>( - mojom::NodeDataStatus::kUnexpectedError, std::vector<NodeData>())); - - // We pretend that the button is the correct element. - SelectorProto proto = ToSelectorProto("#button"); - auto* semantic_information = proto.mutable_semantic_information(); - semantic_information->set_semantic_role(1); - semantic_information->set_objective(2); - semantic_information->set_check_matches_css_element(true); - RunStrictElementCheck(Selector(proto), true); + SetElementValue(backend_node_id, expected_value, + /* send_events= */ true, _)) + .WillOnce(RunOnceCallback<3>(true)); - ASSERT_EQ(log_info_.element_finder_info().size(), 1); - const auto& result = - log_info_.element_finder_info(0).semantic_inference_result(); - ASSERT_EQ(1, result.predicted_elements().size()); - EXPECT_EQ(backend_node_id, result.predicted_elements(0).backend_node_id()); - EXPECT_THAT( - 1, result.predicted_elements(0).semantic_information().semantic_role()); - EXPECT_THAT(2, - result.predicted_elements(0).semantic_information().objective()); - EXPECT_TRUE(result.predicted_elements(0).matches_css_element()); + ClientStatus fill_status; + base::RunLoop run_loop; + web_controller_->SetNativeValue( + "native", input, + base::BindOnce(&WebControllerBrowserTest::OnClientStatus, + base::Unretained(this), run_loop.QuitClosure(), + &fill_status)); + run_loop.Run(); + + EXPECT_EQ(ACTION_APPLIED, fill_status.proto_status()); } } // namespace autofill_assistant |