blob: 56c861ee089c090416c612c903ef1a48996ceaf5 [file] [log] [blame]
// 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.
#ifndef CHROME_BROWSER_UI_SAFETY_HUB_SAFETY_HUB_SERVICE_H_
#define CHROME_BROWSER_UI_SAFETY_HUB_SAFETY_HUB_SERVICE_H_
#include <memory>
#include <optional>
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/safety_hub/safety_hub_result.h"
#include "components/keyed_service/core/keyed_service.h"
// Base class for Safety Hub services. The background and UI tasks of the
// derived classes will be executed periodically, according to the time delta
// interval returned by GetRepeatedUpdateInterval().
class SafetyHubService : public KeyedService {
public:
class Observer : public base::CheckedObserver {
public:
// Called when the result from the update of the service is available.
virtual void OnResultAvailable(const SafetyHubResult* result) = 0;
};
SafetyHubService();
SafetyHubService(const SafetyHubService&) = delete;
SafetyHubService& operator=(const SafetyHubService&) = delete;
~SafetyHubService() override;
// Makes an asynchronous call to the background task, which will be followed
// by the UI task.
void UpdateAsync();
// Adds an observer to be notified when a new result is available.
void AddObserver(Observer* observer);
// Removes an observer from the observer list.
void RemoveObserver(Observer* observer);
// Indicates whether the update process is currently running.
bool IsUpdateRunning();
// Returns the latest result that is available in memory.
std::optional<std::unique_ptr<SafetyHubResult>> GetCachedResult();
// KeyedService implementation.
void Shutdown() override;
// Checks if the repeating timer is running.
bool IsTimerRunningForTesting();
protected:
// Triggers the repeated update task that updates the state of the Safety Hub
// service.
void StartRepeatedUpdates();
// Stops the repeating timer to stop recurring tasks.
void StopTimer();
// SafetyHubService overrides.
// Initializes the latest result such that it is available in memory. It needs
// to be called on creation of the service.
void InitializeLatestResult();
// The value returned by this function determines the interval of how often
// the Update function will be called.
virtual base::TimeDelta GetRepeatedUpdateInterval() = 0;
// TODO(crbug.com/40267370): Not each service needs to execute a task in the
// background. The SafetyHubService class should be redesigned such that
// there's no needless boilerplate code needed in this case.
// Should return the background task that will be executed, containing the
// computation-heavy part of the update process. This task should be static
// and not be bound to the service, as it will be executed on a separate
// background thread. As such, only thread-safe parameters should be bound.
// The returned SafetyHubResult will be passed along to the UpdateOnUIThread
// function.
virtual base::OnceCallback<std::unique_ptr<SafetyHubResult>()>
GetBackgroundTask() = 0;
// This function contains the part of the update task that will be executed
// synchronously on the UI thread. Hence, it should not be computation-heavy
// to avoid freezing the browser. It will be passed the intermediate result
// that was produced by the background task. The result returned by this UI
// task will be the final result that will be sent to the observers.
virtual std::unique_ptr<SafetyHubResult> UpdateOnUIThread(
std::unique_ptr<SafetyHubResult> result) = 0;
virtual base::WeakPtr<SafetyHubService> GetAsWeakRef() = 0;
// Returns the result that should be initialized upon starting the service.
// Typically, this will be the outcome of running the lightweight step of the
// update process (i.e. `UpdateOnUIThread()`).
virtual std::unique_ptr<SafetyHubResult> InitializeLatestResultImpl() = 0;
// Updates the latest result to the provided value.
void SetLatestResult(std::unique_ptr<SafetyHubResult> result);
private:
FRIEND_TEST_ALL_PREFIXES(SafetyHubServiceTest, ManageObservers);
FRIEND_TEST_ALL_PREFIXES(SafetyHubServiceTest, UpdateOnBackgroundThread);
// Called as soon as the update has been finished.
void OnUpdateFinished(std::unique_ptr<SafetyHubResult> result);
// Notifies each of the added observers that a new result is available.
void NotifyObservers(SafetyHubResult* result);
// Posts the background task on a background thread.
void UpdateAsyncInternal();
// Repeating timer that runs the recurring tasks.
base::RepeatingTimer update_timer_;
// List of observers that have to be notified when a new result is available.
base::ObserverList<Observer> observers_;
// Indicator of how many requested updates are still pending.
int pending_updates_ = 0;
// The latest available result, which is initialized when the service is
// started. The value is set by `InitializeLatestResult()`, which is called
// in the constructor of each service.
std::unique_ptr<SafetyHubResult> latest_result_ = nullptr;
};
#endif // CHROME_BROWSER_UI_SAFETY_HUB_SAFETY_HUB_SERVICE_H_