blob: 482a4d7da0a3c93b0403686a5b87a88711dccfde [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/retry_timer.h"
#include <algorithm>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/numerics/clamped_math.h"
#include "components/autofill_assistant/browser/client_status.h"
namespace autofill_assistant {
RetryTimer::RetryTimer(base::TimeDelta period) : period_(period) {}
RetryTimer::~RetryTimer() = default;
void RetryTimer::Start(
base::TimeDelta max_wait_time,
base::RepeatingCallback<void(base::OnceCallback<void(const ClientStatus&)>)>
task,
base::OnceCallback<void(const ClientStatus&)> on_done) {
Reset();
task_ = std::move(task);
on_done_ = std::move(on_done);
remaining_attempts_ =
base::ClampAdd(1, std::max(int64_t{0}, max_wait_time / period_));
RunTask();
}
void RetryTimer::Cancel() {
if (!on_done_)
return;
Reset();
}
void RetryTimer::Reset() {
timer_.reset();
task_id_++; // cancels any pending OnTaskDone callbacks
task_.Reset();
on_done_.Reset();
}
void RetryTimer::RunTask() {
task_.Run(base::BindOnce(&RetryTimer::OnTaskDone,
weak_ptr_factory_.GetWeakPtr(), task_id_));
}
void RetryTimer::OnTaskDone(int64_t task_id, const ClientStatus& status) {
if (task_id != task_id_) // Ignore callbacks from cancelled tasks
return;
remaining_attempts_--;
if (status.ok() || remaining_attempts_ <= 0) {
CHECK_GE(remaining_attempts_, 0);
task_.Reset(); // release any resources held by the callback
std::move(on_done_).Run(status);
// Don't do anything after calling on_done_, as it could have deleted this.
return;
}
timer_ = std::make_unique<base::OneShotTimer>();
timer_->Start(FROM_HERE, period_,
base::BindOnce(&RetryTimer::RunTask,
// Safe, since timer_ is owned by this instance
base::Unretained(this)));
}
} // namespace autofill_assistant