Commit e60ea37c authored by sandromaggi's avatar sandromaggi Committed by Commit Bot

[Autofill Assistant] Simplify WaitForDocumentReadyState

The previous implementation used a differing strategy
based on the optional selector. This CL changes to use
the |EvaluateParams| based approach for both cases.

This is step 1 in a plan to refactor
* WaitForDocumentReadyState
* WaitForDocumentToBecomeInteractive
to become one.

Bug: b/172542134
Change-Id: I5d8cd765e4cb4e922bd3f5e65a03678caa0d52c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2523176
Commit-Queue: Sandro Maggi <sandromaggi@google.com>
Reviewed-by: default avatarMathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825707}
parent 18f2790f
...@@ -223,18 +223,20 @@ std::string DocumentReadyStateToQuotedJsString(int state) { ...@@ -223,18 +223,20 @@ std::string DocumentReadyStateToQuotedJsString(int state) {
// Appends to |out| the definition of a function that'll wait for a // Appends to |out| the definition of a function that'll wait for a
// ready state, expressed as a DocumentReadyState enum value. // ready state, expressed as a DocumentReadyState enum value.
void AppendWaitForDocumentReadyStateFunction(std::string* out) { void AppendWaitForDocumentReadyStateFunction(DocumentReadyState min_ready_state,
std::string* out) {
// quoted_names covers all possible DocumentReadyState values. // quoted_names covers all possible DocumentReadyState values.
std::vector<std::string> quoted_names(DOCUMENT_MAX_READY_STATE + 1); std::vector<std::string> quoted_names(DOCUMENT_MAX_READY_STATE + 1);
for (int i = 0; i <= DOCUMENT_MAX_READY_STATE; i++) { for (int i = 0; i <= DOCUMENT_MAX_READY_STATE; i++) {
quoted_names[i] = DocumentReadyStateToQuotedJsString(i); quoted_names[i] = DocumentReadyStateToQuotedJsString(i);
} }
base::StrAppend(out, {R"(function (minReadyStateNum) { base::StrAppend(
out, {R"((function (minReadyStateNum) {
return new Promise((fulfill, reject) => { return new Promise((fulfill, reject) => {
let handler = function(event) { let handler = function(event) {
let readyState = document.readyState; let readyState = document.readyState;
let readyStates = [)", let readyStates = [)",
base::JoinString(quoted_names, ", "), R"(]; base::JoinString(quoted_names, ", "), R"(];
let readyStateNum = readyStates.indexOf(readyState); let readyStateNum = readyStates.indexOf(readyState);
if (readyStateNum == -1) readyStateNum = 0; if (readyStateNum == -1) readyStateNum = 0;
if (readyStateNum >= minReadyStateNum) { if (readyStateNum >= minReadyStateNum) {
...@@ -245,27 +247,8 @@ void AppendWaitForDocumentReadyStateFunction(std::string* out) { ...@@ -245,27 +247,8 @@ void AppendWaitForDocumentReadyStateFunction(std::string* out) {
document.addEventListener('readystatechange', handler) document.addEventListener('readystatechange', handler)
handler(); handler();
}) })
})"}); }))",
} base::StringPrintf("(%d)", static_cast<int>(min_ready_state))});
// Forward the result of WaitForDocumentReadyState to the callback. The same
// code work on both EvaluateResult and CallFunctionOnResult.
template <typename T>
void OnWaitForDocumentReadyState(
base::OnceCallback<void(const ClientStatus&,
DocumentReadyState,
base::TimeDelta)> callback,
base::TimeTicks wait_start_time,
const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<T> result) {
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
VLOG_IF(1, !status.ok()) << __func__
<< " Failed to get document ready state.";
int ready_state;
SafeGetIntValue(result->GetResult(), &ready_state);
std::move(callback).Run(status, static_cast<DocumentReadyState>(ready_state),
base::TimeTicks::Now() - wait_start_time);
} }
void WrapCallbackNoWait( void WrapCallbackNoWait(
...@@ -748,20 +731,8 @@ void WebController::WaitForDocumentReadyState( ...@@ -748,20 +731,8 @@ void WebController::WaitForDocumentReadyState(
DocumentReadyState, DocumentReadyState,
base::TimeDelta)> callback) { base::TimeDelta)> callback) {
if (optional_frame.empty()) { if (optional_frame.empty()) {
std::string expression; OnFindElementForWaitForDocumentReadyState(
expression.append("("); min_ready_state, std::move(callback), OkClientStatus(), nullptr);
AppendWaitForDocumentReadyStateFunction(&expression);
base::StringAppendF(&expression, ")(%d)",
static_cast<int>(min_ready_state));
devtools_client_->GetRuntime()->Evaluate(
runtime::EvaluateParams::Builder()
.SetExpression(expression)
.SetReturnByValue(true)
.SetAwaitPromise(true)
.Build(),
/* node_frame_id= */ std::string(),
base::BindOnce(&OnWaitForDocumentReadyState<runtime::EvaluateResult>,
std::move(callback), base::TimeTicks::Now()));
return; return;
} }
FindElement( FindElement(
...@@ -784,23 +755,35 @@ void WebController::OnFindElementForWaitForDocumentReadyState( ...@@ -784,23 +755,35 @@ void WebController::OnFindElementForWaitForDocumentReadyState(
return; return;
} }
std::string function_declaration; std::string expression;
AppendWaitForDocumentReadyStateFunction(&function_declaration); AppendWaitForDocumentReadyStateFunction(min_ready_state, &expression);
devtools_client_->GetRuntime()->Evaluate(
std::vector<std::unique_ptr<runtime::CallArgument>> arguments; runtime::EvaluateParams::Builder()
AddRuntimeCallArgument(static_cast<int>(min_ready_state), &arguments); .SetExpression(expression)
devtools_client_->GetRuntime()->CallFunctionOn(
runtime::CallFunctionOnParams::Builder()
.SetObjectId(element ? element->object_id : "")
.SetFunctionDeclaration(function_declaration)
.SetArguments(std::move(arguments))
.SetReturnByValue(true) .SetReturnByValue(true)
.SetAwaitPromise(true) .SetAwaitPromise(true)
.Build(), .Build(),
element->node_frame_id, /* node_frame_id= */ element ? element->node_frame_id : std::string(),
base::BindOnce( base::BindOnce(&WebController::OnWaitForDocumentReadyState,
&OnWaitForDocumentReadyState<runtime::CallFunctionOnResult>, weak_ptr_factory_.GetWeakPtr(), std::move(callback),
std::move(callback), base::TimeTicks::Now())); base::TimeTicks::Now()));
}
void WebController::OnWaitForDocumentReadyState(
base::OnceCallback<void(const ClientStatus&,
DocumentReadyState,
base::TimeDelta)> callback,
base::TimeTicks wait_start_time,
const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result) {
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
VLOG_IF(1, !status.ok()) << __func__
<< " Failed to get document ready state.";
int ready_state;
SafeGetIntValue(result->GetResult(), &ready_state);
std::move(callback).Run(status, static_cast<DocumentReadyState>(ready_state),
base::TimeTicks::Now() - wait_start_time);
} }
void WebController::FindElement(const Selector& selector, void WebController::FindElement(const Selector& selector,
......
...@@ -431,6 +431,13 @@ class WebController { ...@@ -431,6 +431,13 @@ class WebController {
base::TimeDelta)> callback, base::TimeDelta)> callback,
const ClientStatus& status, const ClientStatus& status,
std::unique_ptr<ElementFinder::Result> element); std::unique_ptr<ElementFinder::Result> element);
void OnWaitForDocumentReadyState(
base::OnceCallback<void(const ClientStatus&,
DocumentReadyState,
base::TimeDelta)> callback,
base::TimeTicks wait_start_time,
const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result);
// Wrapper for calling the |callback| after re-enabling the keyboard by // Wrapper for calling the |callback| after re-enabling the keyboard by
// setting the assistant action state to "not running". // setting the assistant action state to "not running".
......
...@@ -2054,20 +2054,35 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ...@@ -2054,20 +2054,35 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
} }
IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
WaitFrameDocumentReadyStateLoaded) { WaitFrameDocumentReadyStateComplete) {
ClientStatus status; ClientStatus status;
DocumentReadyState end_state; DocumentReadyState end_state;
base::RunLoop run_loop; base::RunLoop run_loop;
web_controller_->WaitForDocumentReadyState( web_controller_->WaitForDocumentReadyState(
Selector({"#iframe"}), DOCUMENT_LOADED, Selector({"#iframe"}), DOCUMENT_COMPLETE,
base::BindOnce(&WebControllerBrowserTest::OnClientStatusAndReadyState, base::BindOnce(&WebControllerBrowserTest::OnClientStatusAndReadyState,
base::Unretained(this), run_loop.QuitClosure(), &status, base::Unretained(this), run_loop.QuitClosure(), &status,
&end_state)); &end_state));
run_loop.Run(); run_loop.Run();
EXPECT_EQ(ACTION_APPLIED, status.proto_status()) << "Status: " << status; EXPECT_EQ(ACTION_APPLIED, status.proto_status()) << "Status: " << status;
EXPECT_THAT(end_state, EXPECT_THAT(end_state, DOCUMENT_COMPLETE);
AnyOf(DOCUMENT_LOADED, DOCUMENT_INTERACTIVE, DOCUMENT_COMPLETE)); }
IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
WaitExternalFrameDocumentReadyStateComplete) {
ClientStatus status;
DocumentReadyState end_state;
base::RunLoop run_loop;
web_controller_->WaitForDocumentReadyState(
Selector({"#iframeExternal"}), DOCUMENT_COMPLETE,
base::BindOnce(&WebControllerBrowserTest::OnClientStatusAndReadyState,
base::Unretained(this), run_loop.QuitClosure(), &status,
&end_state));
run_loop.Run();
EXPECT_EQ(ACTION_APPLIED, status.proto_status()) << "Status: " << status;
EXPECT_THAT(end_state, DOCUMENT_COMPLETE);
} }
IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetElementRect) { IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetElementRect) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment