blob: 047f77ea6522e4b0dac9c2514fb5e6eb9d191339 [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 "base/bind.h"
#include "base/bind_helpers.h"
namespace autofill_assistant {
RetryTimer::RetryTimer(base::TimeDelta period)
: period_(period), weak_ptr_factory_(this) {}
RetryTimer::~RetryTimer() = default;
void RetryTimer::Start(
base::TimeDelta max_wait_time,
base::RepeatingCallback<void(base::OnceCallback<void(bool)>)> task,
base::OnceCallback<void(bool)> on_done) {
Reset();
task_ = std::move(task);
on_done_ = std::move(on_done);
if (max_wait_time <= base::TimeDelta::FromSeconds(0)) {
remaining_attempts_ = 1;
} else {
remaining_attempts_ = 1 + max_wait_time / period_;
}
DCHECK_GE(remaining_attempts_, 1);
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, bool success) {
if (task_id != task_id_) // Ignore callbacks from cancelled tasks
return;
remaining_attempts_--;
if (success || remaining_attempts_ <= 0) {
CHECK_GE(remaining_attempts_, 0);
task_.Reset(); // release any resources held by the callback
std::move(on_done_).Run(success);
// 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