File: safety_hub_service.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (189 lines) | stat: -rw-r--r-- 7,424 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// 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 <string>

#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "components/keyed_service/core/keyed_service.h"

inline constexpr char kSafetyHubTimestampResultKey[] = "timestamp";
inline constexpr char kSafetyHubOriginKey[] = "origin";

// 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:
  // Base class for results returned after the periodic execution of the Safety
  // Hub service. Each service should implement a derived class that captures
  // the specific information that is retrieved. Any intermediate data that is
  // required for the background task, or that needs to passed through to the UI
  // thread task should be included as well.
  // TODO(crbug.com/40267370): Move result class to outside of SafetyHubService.
  class Result {
   public:
    virtual ~Result() = default;

    virtual base::Value::Dict ToDictValue() const = 0;

    // Determines whether the current result meets the bar for showing a
    // notification to the user in the Chrome menu.
    virtual bool IsTriggerForMenuNotification() const = 0;

    // Determines whether the previous result is sufficiently different that for
    // the current result a new notification should be shown. This indication is
    // just based on the comparison of the two results, and thus irrelevant to
    // how frequently a menu notification has already been shown.
    virtual bool WarrantsNewMenuNotification(
        const base::Value::Dict& previous_result_dict) const = 0;

    // Returns the string for the notification that will be shown in the
    // three-dot menu.
    virtual std::u16string GetNotificationString() const = 0;

    // Returns the command ID that should be run when the user clicks the
    // notification in the three-dot menu.
    virtual int GetNotificationCommandId() const = 0;

    // Returns a copy of the current Safety Hub object. This is intended to be
    // used when the caller is unaware of the specific derived class.
    virtual std::unique_ptr<Result> Clone() const = 0;

    base::Time timestamp() const;

   protected:
    explicit Result(base::Time timestamp = base::Time::Now());
    Result(const Result&) = default;
    Result& operator=(const Result&) = default;

    base::Value::Dict BaseToDictValue() const;

   private:
    base::Time timestamp_;
  };

  class Observer : public base::CheckedObserver {
   public:
    // Called when the result from the update of the service is available.
    virtual void OnResultAvailable(const Result* 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<SafetyHubService::Result>> 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 Result will be passed along to the UpdateOnUIThread function.
  virtual base::OnceCallback<std::unique_ptr<Result>()> 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<Result> UpdateOnUIThread(
      std::unique_ptr<Result> 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<SafetyHubService::Result>
  InitializeLatestResultImpl() = 0;

  // Updates the latest result to the provided value.
  void SetLatestResult(std::unique_ptr<SafetyHubService::Result> 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<Result> result);

  // Notifies each of the added observers that a new result is available.
  void NotifyObservers(Result* 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<Result> latest_result_ = nullptr;
};

#endif  // CHROME_BROWSER_UI_SAFETY_HUB_SAFETY_HUB_SERVICE_H_