| // Copyright 2019 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_ANDROID_USAGE_STATS_USAGE_STATS_DATABASE_H_ |
| #define CHROME_BROWSER_ANDROID_USAGE_STATS_USAGE_STATS_DATABASE_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/containers/queue.h" |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "components/leveldb_proto/public/proto_database.h" |
| |
| class Profile; |
| |
| namespace usage_stats { |
| |
| class WebsiteEvent; |
| class Suspension; |
| class TokenMapping; |
| |
| using leveldb_proto::ProtoDatabase; |
| |
| // Stores website events, suspensions and token to fully-qualified domain name |
| // (FQDN) mappings in LevelDB. |
| class UsageStatsDatabase { |
| public: |
| enum class Error { kNoError, kUnknownError }; |
| |
| using EventsCallback = |
| base::OnceCallback<void(Error, std::vector<WebsiteEvent>)>; |
| |
| using SuspensionsCallback = |
| base::OnceCallback<void(Error, std::vector<std::string>)>; |
| |
| using TokenMap = std::map<std::string, std::string>; |
| using TokenMappingsCallback = base::OnceCallback<void(Error, TokenMap)>; |
| |
| using StatusCallback = base::OnceCallback<void(Error)>; |
| |
| // Digital Wellbeing doesn't show activity older than a week, so 7 days is the |
| // max age for event retention. |
| constexpr static int EXPIRY_THRESHOLD_DAYS = 7; |
| |
| // Initializes the database with user |profile|. |
| explicit UsageStatsDatabase(Profile* profile); |
| |
| UsageStatsDatabase(const UsageStatsDatabase&) = delete; |
| UsageStatsDatabase& operator=(const UsageStatsDatabase&) = delete; |
| |
| ~UsageStatsDatabase(); |
| |
| void GetAllEvents(EventsCallback callback); |
| |
| // Get all events in range between |startTime| (inclusive) and |endTime| |
| // (exclusive) at second-level granularity. |
| void QueryEventsInRange(base::Time startTime, |
| base::Time endTime, |
| EventsCallback callback); |
| |
| void AddEvents(std::vector<WebsiteEvent> events, StatusCallback callback); |
| |
| void DeleteAllEvents(StatusCallback callback); |
| |
| // Delete all events in range between |startTime| (inclusive) and |
| // |endTime| (exclusive) at second-level granularity. |
| void DeleteEventsInRange(base::Time startTime, |
| base::Time endTime, |
| StatusCallback callback); |
| |
| void DeleteEventsWithMatchingDomains(base::flat_set<std::string> domains, |
| StatusCallback callback); |
| |
| // Delete events older than EXPIRY_THRESHOLD_DAYS. |
| void ExpireEvents(base::Time now); |
| |
| void GetAllSuspensions(SuspensionsCallback callback); |
| |
| // Persists all the suspensions in |domains| and deletes any suspensions *not* |
| // in |domains|. |
| void SetSuspensions(base::flat_set<std::string> domains, |
| StatusCallback callback); |
| |
| void GetAllTokenMappings(TokenMappingsCallback callback); |
| |
| // Persists all the mappings in |mappings| and deletes any mappings *not* in |
| // |mappings|. The map's key is the token, and its value is the FQDN. |
| void SetTokenMappings(TokenMap mappings, StatusCallback callback); |
| |
| protected: |
| // For testing only. |
| UsageStatsDatabase( |
| std::unique_ptr<ProtoDatabase<WebsiteEvent>> website_event_db, |
| std::unique_ptr<ProtoDatabase<Suspension>> suspension_db, |
| std::unique_ptr<ProtoDatabase<TokenMapping>> token_mapping_db); |
| |
| private: |
| void InitializeDBs(); |
| |
| void OnWebsiteEventInitDone(bool retry, |
| leveldb_proto::Enums::InitStatus status); |
| |
| void OnSuspensionInitDone(bool retry, |
| leveldb_proto::Enums::InitStatus status); |
| |
| void OnTokenMappingInitDone(bool retry, |
| leveldb_proto::Enums::InitStatus status); |
| |
| void OnWebsiteEventExpiryDone(Error error); |
| |
| void OnUpdateEntries(StatusCallback callback, bool isSuccess); |
| |
| void OnLoadEntriesForGetAllEvents( |
| EventsCallback callback, |
| bool isSuccess, |
| std::unique_ptr<std::vector<WebsiteEvent>> stats); |
| |
| void OnLoadEntriesForQueryEventsInRange( |
| EventsCallback callback, |
| bool isSuccess, |
| std::unique_ptr<std::map<std::string, WebsiteEvent>> event_map); |
| |
| void OnLoadEntriesForDeleteEventsInRange( |
| StatusCallback callback, |
| bool isSuccess, |
| std::unique_ptr<std::map<std::string, WebsiteEvent>> event_map); |
| |
| void OnLoadEntriesForGetAllSuspensions( |
| SuspensionsCallback callback, |
| bool isSuccess, |
| std::unique_ptr<std::vector<Suspension>> suspensions); |
| |
| void OnLoadEntriesForGetAllTokenMappings( |
| TokenMappingsCallback callback, |
| bool isSuccess, |
| std::unique_ptr<std::vector<TokenMapping>> mappings); |
| |
| std::unique_ptr<ProtoDatabase<WebsiteEvent>> website_event_db_; |
| std::unique_ptr<ProtoDatabase<Suspension>> suspension_db_; |
| std::unique_ptr<ProtoDatabase<TokenMapping>> token_mapping_db_; |
| |
| // Track initialization state of proto databases. |
| bool website_event_db_initialized_; |
| bool suspension_db_initialized_; |
| bool token_mapping_db_initialized_; |
| |
| // Store callbacks for delayed execution once database is initialized. |
| base::queue<base::OnceClosure> website_event_db_callbacks_; |
| base::queue<base::OnceClosure> suspension_db_callbacks_; |
| base::queue<base::OnceClosure> token_mapping_db_callbacks_; |
| |
| base::WeakPtrFactory<UsageStatsDatabase> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace usage_stats |
| |
| #endif // CHROME_BROWSER_ANDROID_USAGE_STATS_USAGE_STATS_DATABASE_H_ |