#ifndef CHROME_BROWSER_ACTOR_TOOLS_OBSERVATION_DELAY_CONTROLLER_H_
#define CHROME_BROWSER_ACTOR_TOOLS_OBSERVATION_DELAY_CONTROLLER_H_
#include <memory>
#include <ostream>
#include <string_view>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/actor/aggregated_journal.h"
#include "chrome/common/actor.mojom.h"
#include "chrome/common/actor/task_id.h"
#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace content {
class RenderFrameHost;
}
namespace actor {
class ObservationDelayMetrics;
class ObservationDelayController : public content::WebContentsObserver {
public:
enum class Result {
kOk,
kPageNavigated,
};
using ReadyCallback = base::OnceCallback<void(Result)>;
struct PageStabilityConfig {
bool supports_paint_stability = false;
base::TimeDelta start_delay;
};
ObservationDelayController(content::RenderFrameHost& target_frame,
TaskId task_id,
AggregatedJournal& journal,
PageStabilityConfig page_stability_config);
ObservationDelayController(TaskId task_id, AggregatedJournal& journal);
~ObservationDelayController() override;
void Wait(tabs::TabInterface& target_tab, ReadyCallback callback);
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
void DidStopLoading() override;
size_t NavigationCount() const;
void SetNavigationCount(size_t);
enum class State {
kInitial,
kWaitForPageStability,
kPageStabilityMonitorDisconnected,
kWaitForLoadCompletion,
kWaitForVisualStateUpdate,
kMaybeDelayForLcp,
kDelayForLcp,
kDidTimeout,
kPageNavigated,
kDone
};
static std::string_view StateToString(State state);
protected:
virtual void SetState(State state);
State state_ = State::kInitial;
mojo::Remote<mojom::PageStabilityMonitor> page_stability_monitor_remote_;
private:
friend std::ostream& operator<<(
std::ostream& o,
const ObservationDelayController::State& state);
void OnPageStable();
void OnVisualStateUpdated(bool);
void OnMonitorDisconnected();
void DCheckStateTransition(State old_state, State new_state);
void MoveToState(State state);
base::OnceClosure MoveToStateClosure(State new_state);
base::OnceClosure PostMoveToStateClosure(
State new_state,
base::TimeDelta delay = base::TimeDelta());
ReadyCallback ready_callback_;
Result result_ = Result::kOk;
base::raw_ref<AggregatedJournal> journal_;
TaskId task_id_;
size_t navigation_count_ = 0;
std::unique_ptr<AggregatedJournal::PendingAsyncEntry> wait_journal_entry_;
std::unique_ptr<AggregatedJournal::PendingAsyncEntry> inner_journal_entry_;
base::TimeDelta page_stability_start_delay_;
std::unique_ptr<ObservationDelayMetrics> metrics_;
base::WeakPtrFactory<ObservationDelayController> weak_ptr_factory_{this};
};
}
#endif