// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/enterprise/model/idle/action_runner_impl.h"
#import <iterator>
#import "base/functional/bind.h"
#import "base/ranges/algorithm.h"
#import "components/enterprise/idle/idle_pref_names.h"
#import "components/enterprise/idle/metrics.h"
#import "components/prefs/pref_service.h"
#import "ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h"
namespace enterprise_idle {
ActionRunnerImpl::ActionRunnerImpl(ChromeBrowserState* browser_state)
: browser_state_(browser_state),
action_factory_(std::make_unique<ActionFactory>()) {}
ActionRunnerImpl::~ActionRunnerImpl() = default;
void ActionRunnerImpl::Run(
ActionsCompletedCallback actions_completed_callback) {
actions_completed_callback_ = std::move(actions_completed_callback);
ActionQueue actions = GetActions();
if (actions.empty()) {
return;
}
actions_start_time_ = base::TimeTicks::Now();
RunNextAction(std::move(actions));
}
void ActionRunnerImpl::SetActionFactoryForTesting(
std::unique_ptr<ActionFactory> action_factory) {
action_factory_ = std::move(action_factory);
}
ActionRunnerImpl::ActionQueue ActionRunnerImpl::GetActions() {
std::vector<ActionType> actions;
base::ranges::transform(
browser_state_->GetPrefs()->GetList(prefs::kIdleTimeoutActions),
std::back_inserter(actions), [](const base::Value& action) {
return static_cast<ActionType>(action.GetInt());
});
return action_factory_->Build(
actions, BrowsingDataRemoverFactory::GetForBrowserState(browser_state_),
BrowsingDataRemoverFactory::GetForBrowserState(
browser_state_->GetOffTheRecordChromeBrowserState()));
}
void ActionRunnerImpl::RunNextAction(ActionQueue actions) {
DUMP_WILL_BE_CHECK(!actions.empty());
const std::unique_ptr<Action>& action = actions.top();
action->Run(
browser_state_,
base::BindOnce(&ActionRunnerImpl::OnActionFinished,
weak_ptr_factory_.GetWeakPtr(), std::move(actions)));
}
void ActionRunnerImpl::OnActionFinished(ActionQueue remaining_actions,
bool succeeded) {
remaining_actions.pop();
if (!succeeded) {
// Previous action failed. Log failure and abort.
metrics::RecordActionsSuccess(metrics::IdleTimeoutActionType::kAllActions,
false);
return;
}
if (remaining_actions.empty()) {
// All done. Run callback to show snackbar.
// Callback can be empty in tests.
if (actions_completed_callback_) {
metrics::RecordActionsSuccess(metrics::IdleTimeoutActionType::kAllActions,
true);
metrics::RecordIdleTimeoutActionTimeTaken(
metrics::IdleTimeoutActionType::kAllActions,
base::TimeTicks::Now() - actions_start_time_);
std::move(actions_completed_callback_).Run();
}
return;
}
RunNextAction(std::move(remaining_actions));
}
} // namespace enterprise_idle