chrome/browser/ui/safety_hub/README.md
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.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::DictValue as argument
and restores the properties that are defined in the dictionary.
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.