Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / browsing_topics / browsing_topics_state.h
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_STATE_H_
6 #define COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_STATE_H_
7
8 #include "base/containers/queue.h"
9 #include "base/files/important_file_writer.h"
10 #include "base/gtest_prod_util.h"
11 #include "base/task/sequenced_task_runner.h"
12 #include "base/time/time.h"
13 #include "components/browsing_topics/common/common_types.h"
14 #include "components/browsing_topics/epoch_topics.h"
15
16 namespace browsing_topics {
17
18 // Contains the data needed to calculate the browsing topics when a context
19 // requests it via document.browsingTopics(). The data is backed by a JSON file:
20 // when `BrowsingTopicsState` is initialized, the state members will be read
21 // from the file on a backend thread, and all overwriting methods will schedule
22 // an update to the file. The `BrowsingTopicsState`'s owner should listen on the
23 // `loaded_callback` notification. Before the loading finishes, it's disallowed
24 // to access this `BrowsingTopicsState`.
25 class BrowsingTopicsState
26     : public base::ImportantFileWriter::BackgroundDataSerializer {
27  public:
28   struct LoadResult {
29     LoadResult(bool file_exists, std::unique_ptr<base::Value> value);
30     ~LoadResult();
31
32     LoadResult(const LoadResult&) = delete;
33     LoadResult& operator=(const LoadResult&) = delete;
34     LoadResult(LoadResult&&) = delete;
35     LoadResult& operator=(LoadResult&&) = delete;
36
37     bool file_exists = false;
38
39     // The deserialized value from the content of the json file.
40     std::unique_ptr<base::Value> value;
41   };
42
43   // The result of parsing a `LoadResult::value` to the `BrowsingTopicsState`.
44   struct ParseResult {
45     // Whether the parsing was successful. Parsing can fail due to corrupted
46     // data.
47     bool success = false;
48
49     // Whether `BrowsingTopicsState` should be saved to the file after parsing.
50     // Saving is needed if the config version has been updated, or if an error
51     // is encountered (to clean up unneeded data). In the common case where the
52     // data is loaded from a pre-existing file, the file save isn't necessary.
53     bool should_save_state_to_file = false;
54   };
55
56   explicit BrowsingTopicsState(const base::FilePath& profile_path,
57                                base::OnceClosure loaded_callback);
58
59   ~BrowsingTopicsState() override;
60
61   BrowsingTopicsState(const BrowsingTopicsState&) = delete;
62   BrowsingTopicsState& operator=(const BrowsingTopicsState&) = delete;
63   BrowsingTopicsState(BrowsingTopicsState&&) = delete;
64   BrowsingTopicsState& operator=(BrowsingTopicsState&&) = delete;
65
66   // Clear `epochs_`.
67   void ClearAllTopics();
68
69   // Clear the topics data at `epochs_[epoch_index]`. Note that this doesn't
70   // remove the entry from `epochs_`.
71   void ClearOneEpoch(size_t epoch_index);
72
73   // Clear the topic and observing domains data for `topic`.
74   void ClearTopic(Topic topic);
75
76   // Clear the observing domains data in `epochs_`  that match
77   // `hashed_context_domain`.
78   void ClearContextDomain(const HashedDomain& hashed_context_domain);
79
80   // Append `epoch_topics` to `epochs_`. This is invoked at the end of each
81   // epoch calculation. If an old EpochTopics is removed as a result, return it.
82   absl::optional<EpochTopics> AddEpoch(EpochTopics epoch_topics);
83
84   // Set `next_scheduled_calculation_time_` to one epoch later from
85   // base::Time::Now(). This is invoked at the end of each epoch calculation.
86   void UpdateNextScheduledCalculationTime();
87
88   // Calculate the candidate epochs to derive the topics from on `top_domain`.
89   // The caller (i.e. BrowsingTopicsServiceImpl, which also holds `this`) is
90   // responsible for ensuring that the `EpochTopic` objects that the pointers
91   // refer to remain alive when the caller is accessing them.
92   std::vector<const EpochTopics*> EpochsForSite(
93       const std::string& top_domain) const;
94
95   const base::circular_deque<EpochTopics>& epochs() const {
96     DCHECK(loaded_);
97     return epochs_;
98   }
99
100   base::Time next_scheduled_calculation_time() const {
101     DCHECK(loaded_);
102     return next_scheduled_calculation_time_;
103   }
104
105   ReadOnlyHmacKey hmac_key() const {
106     DCHECK(loaded_);
107     return hmac_key_;
108   }
109
110   bool HasScheduledSaveForTesting() const;
111
112  private:
113   FRIEND_TEST_ALL_PREFIXES(BrowsingTopicsStateTest,
114                            EpochsForSite_OneEpoch_SwitchTimeNotArrived);
115   FRIEND_TEST_ALL_PREFIXES(BrowsingTopicsStateTest,
116                            EpochsForSite_OneEpoch_SwitchTimeArrived);
117   FRIEND_TEST_ALL_PREFIXES(BrowsingTopicsStateTest,
118                            EpochsForSite_OneEpoch_ManuallyTriggered);
119
120   base::TimeDelta CalculateSiteStickyTimeDelta(
121       const std::string& top_domain) const;
122
123   // ImportantFileWriter::BackgroundDataSerializer implementation.
124   base::ImportantFileWriter::BackgroundDataProducerCallback
125   GetSerializedDataProducerForBackgroundSequence() override;
126
127   base::Value::Dict ToDictValue() const;
128
129   void ScheduleSave();
130
131   void DidLoadFile(base::OnceClosure loaded_callback,
132                    std::unique_ptr<LoadResult> load_result);
133
134   // Parse `value` and populate the state member variables.
135   ParseResult ParseValue(const base::Value& value);
136
137   // Sequenced task runner where disk writes will be performed.
138   scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
139
140   // Helper to write data safely.
141   base::ImportantFileWriter writer_;
142
143   // Contains the browsing topics of the latest epochs, as well as the topics
144   // observed by each context domain in each of the epoch. These entries are in
145   // time ascending order: a new entry will be appended to `epochs_` on every
146   // browsing topics calculation, regardless of whether it succeeded or not. We
147   // are only interested in the latest
148   // `kBrowsingTopicsNumberOfEpochsToExpose + 1` epochs (i.e. the epoch
149   // switching time will be per-user, per-site, with a full epoch range of
150   // variance, thus one extra epoch are kept here), so old data will be
151   // automatically removed, and the size of the queue won't exceed that limit.
152   base::circular_deque<EpochTopics> epochs_;
153
154   // The next time a calculation should occur. This will be updated when a
155   // calculation is scheduled at the end of a topics calculation and is always
156   // synchronously updated with `epochs_`.
157   //
158   // next_scheduled_calculation_time_.is_null() indicates this is a new profile
159   // or there was an update to the configuration version when this
160   // `BrowsingTopicsState` is initialized. In either case, `epochs_` will be
161   // empty.
162   base::Time next_scheduled_calculation_time_;
163
164   // The key for calculating the per-user hash numbers. See ./util.h for various
165   // use cases. This key is generated and synced to storage in the first
166   // browsing session. It won't be reset/updated in any case.
167   HmacKey hmac_key_{};
168
169   // Whether the state members are loaded from file. Public accessor methods are
170   // disallowed (except for `HasScheduledSaveForTesting`) before `loaded_`
171   // becomes true.
172   bool loaded_ = false;
173
174   base::WeakPtrFactory<BrowsingTopicsState> weak_ptr_factory_{this};
175 };
176
177 }  // namespace browsing_topics
178
179 #endif  // COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_STATE_H_