blob: 976ad325aded182d173657aa54c470664bce0e89 [file] [log] [blame]
// 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.
#include "components/autofill_assistant/browser/actions/wait_for_document_action.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
namespace autofill_assistant {
WaitForDocumentAction::WaitForDocumentAction(ActionDelegate* delegate,
const ActionProto& proto)
: Action(delegate, proto) {
DCHECK(proto.has_wait_for_document());
}
WaitForDocumentAction::~WaitForDocumentAction() {}
void WaitForDocumentAction::InternalProcessAction(
ProcessActionCallback callback) {
callback_ = std::move(callback);
Selector selector(proto_.wait_for_document().frame());
if (selector.empty()) {
// No element to wait for.
OnShortWaitForElement(ClientStatus(ACTION_APPLIED));
return;
}
delegate_->ShortWaitForElement(
selector, base::BindOnce(&WaitForDocumentAction::OnShortWaitForElement,
weak_ptr_factory_.GetWeakPtr()));
}
void WaitForDocumentAction::OnShortWaitForElement(
const ClientStatus& element_status) {
if (!element_status.ok()) {
SendResult(element_status, DOCUMENT_UNKNOWN_READY_STATE);
return;
}
delegate_->GetDocumentReadyState(
Selector(proto_.wait_for_document().frame()),
base::BindOnce(&WaitForDocumentAction::OnGetStartState,
weak_ptr_factory_.GetWeakPtr()));
}
void WaitForDocumentAction::OnGetStartState(const ClientStatus& status,
DocumentReadyState start_state) {
if (!status.ok()) {
SendResult(status, DOCUMENT_UNKNOWN_READY_STATE);
return;
}
processed_action_proto_->mutable_wait_for_document_result()
->set_start_ready_state(start_state);
if (start_state >= proto_.wait_for_document().min_ready_state()) {
SendResult(OkClientStatus(), start_state);
return;
}
base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
proto_.wait_for_document().timeout_ms());
if (timeout.is_zero()) {
SendResult(ClientStatus(TIMED_OUT), start_state);
return;
}
timer_.Start(FROM_HERE, timeout,
base::BindOnce(&WaitForDocumentAction::OnTimeout,
weak_ptr_factory_.GetWeakPtr()));
delegate_->WaitForDocumentReadyState(
Selector(proto_.wait_for_document().frame()),
proto_.wait_for_document().min_ready_state(),
base::BindOnce(&WaitForDocumentAction::OnWaitForStartState,
weak_ptr_factory_.GetWeakPtr()));
}
void WaitForDocumentAction::OnWaitForStartState(
const ClientStatus& status,
DocumentReadyState current_state) {
SendResult(status, current_state);
}
void WaitForDocumentAction::OnTimeout() {
// We've already returned successfully.
if (!callback_)
return;
delegate_->GetDocumentReadyState(
Selector(proto_.wait_for_document().frame()),
base::BindOnce(&WaitForDocumentAction::OnTimeoutInState,
weak_ptr_factory_.GetWeakPtr()));
}
void WaitForDocumentAction::OnTimeoutInState(const ClientStatus& status,
DocumentReadyState end_state) {
DVLOG_IF(1, !status.ok())
<< __func__ << ": cannot report end_state because of " << status;
SendResult(ClientStatus(TIMED_OUT), end_state);
}
void WaitForDocumentAction::SendResult(const ClientStatus& status,
DocumentReadyState end_state) {
// Only send a result for the first of OnTimeout or OnSuccess that finishes.
if (!callback_)
return;
processed_action_proto_->mutable_wait_for_document_result()
->set_end_ready_state(end_state);
UpdateProcessedAction(status);
std::move(callback_).Run(std::move(processed_action_proto_));
}
} // namespace autofill_assistant