## Services
This directory contains the services related to Safety Hub. Each specific
service inherits from `SafetyHubService`, as defined in `safety_hub_service.h`.
The service will be periodically updated, depending on the frequency determined
by `GetRepeatedUpdateInterval()`. Additionally, an update will be launched every
time that the service is started (whenever the browser is started). Hence, it's
important to note that the update can be called more frequently than the
interval returned by `GetRepeatedUpdateInterval()`.
The update process consists of two stages, a background task and a UI thread
task.
The background task will be run on a separate thread in the background. The
function that needs to be run in the background should contain the functionality
of the update that is the most computation-heavy, to prevent blocking the UI
thread and possibly freezing the browser. The background task can return an
intermediate result, that will be passed along to the UI thread task. Ideally,
the background task should be a static function that will be returned by
`GetBackgroundTask()`. As this will be run in a thread other than the one the
service runs in, any arguments that are bound to the function should be
thread-safe. As the browser shuts down, references to these objects might be
destroyed, possibly leading to memory issues. For instance, a reference to the
service itself should NOT be bound to the function. This will result in crashes
of other tests, and could cause the browser to crash when one profile is shut
down.
The UI thread task needs to be defined in `UpdateOnUIThread()`. It will be
passed the intermediate result (a unique pointer to `SafetyHubService::Result`)
that was returned by the background task. This method will be run synchronously
on the UI thread after the background task has completed. The result by this UI
thread task will be the final result that the observers will be notified of.
`SafetyHubService::Result` will thus be used for 1) passing the intermediate
result of `GetBackgroundTask()` to `UpdateOnUIThread()`, and 2) the final result
that follows from running the update process of the service. To reduce
unnecessary overhead, it is suggested that the final result does not contain any
of the intermediate results, e.g. by creating a new `SafetyHubService::Result`
in `UpdateOnUIThread()`.
In order to make the latest result of the service always available just after
initialization of the service, the `InitializeLatestResult()` needs to be called
in the constructor of the derived services. This function, which also needs to
be implemented by each service, has to set the `latest_result_` property.
Similarly, the `StartRepeatedUpdates()` function should also be called in the
constructor of each service. This method will start up the timer that
periodically run the update.
In summary, each Safety Hub service should implement the following functions:
- `InitializeLatestResult()`: set the `latest_result_` property to the latest
available result.
- `GetRepeatedUpdateInterval()`: returns a `base::TimeDelta` that determines
the minimal frequency of how often the service is updated.
- `GetBackgroundTask()`: returns a bound (static) function that will be
executed in the background, containing the computation-heavy part of the
service's update.
- `UpdateOnUIThread()`: will be run synchronously on the UI thread, and will
further process the intermediate result of the background task.
- `GetAsWeakRef()`: returns a weak pointer to the service, from the
`WeakPtrFactory` of the derived service.
## Results
Each Safety Hub service has their own result type that inherits from
`SafetyHubService::Result`. This result should include the information that is
needed for displaying the information in the UI and being able to distinguish
two different results. To support serialization, the `ToDictValue()` method
needs to be implemented by the derived result classes. Furthermore, the derived
classes should have a constructor that takes a `base::Value::Dict` as argument
and restores the properties that are defined in the dictionary.
## Testing
As updating the service will run a task both in the background as well as on the
UI thread, it is advised to use the helper function
`UpdateSafetyHubServiceAsync(service)`, defined in `safety_hub_test_util.h` to
trigger an update of the service in tests.