blob: 71eac9f394c961594fb3c020ebbb98b99a87ffb7 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2015 The Chromium Authors
peter5bb2e1452015-03-12 15:31:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_DATABASE_H_
6#define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_DATABASE_H_
7
peter05e061b2015-03-13 13:16:068#include <stdint.h>
Daniel Cheng556abd12016-04-02 01:13:089
dcheng59716272016-04-09 05:19:0810#include <memory>
Arthur Sonzognic686e8f2024-01-11 08:36:3711#include <optional>
peteradb2fe22015-03-19 18:49:2812#include <set>
13#include <vector>
peter05e061b2015-03-13 13:16:0614
peter5bb2e1452015-03-12 15:31:1615#include "base/files/file_path.h"
peter5bb2e1452015-03-12 15:31:1616#include "base/sequence_checker.h"
17#include "content/common/content_export.h"
Sharon Yangea520d82018-07-25 20:46:5318#include "content/public/browser/platform_notification_context.h"
peter5bb2e1452015-03-12 15:31:1619
peter513eb552015-03-16 18:55:0420class GURL;
21
Richard Knoll2e136ef2019-03-07 09:45:1122namespace blink {
23struct NotificationResources;
24} // namespace blink
25
peter5bb2e1452015-03-12 15:31:1626namespace leveldb {
27class DB;
28class Env;
peterc1978f942015-04-01 17:38:1829class FilterPolicy;
Sharon Yangea520d82018-07-25 20:46:5330} // namespace leveldb
peter5bb2e1452015-03-12 15:31:1631
32namespace content {
33
peter513eb552015-03-16 18:55:0434struct NotificationDatabaseData;
35
peter5bb2e1452015-03-12 15:31:1636// Implementation of the persistent notification database.
37//
peter8f7612682015-03-16 20:11:1538// The database is built on top of a LevelDB database, either in memory or on
39// the filesystem depending on the path passed to the constructor. When writing
40// a new notification, it will be assigned an id guaranteed to be unique for the
41// lifetime of the database.
42//
43// This class must only be used on a thread or sequenced task runner that allows
44// file I/O. The same thread or task runner must be used for all method calls.
peter5bb2e1452015-03-12 15:31:1645class CONTENT_EXPORT NotificationDatabase {
46 public:
Sharon Yangea520d82018-07-25 20:46:5347 using UkmCallback =
48 base::RepeatingCallback<void(const NotificationDatabaseData&)>;
Richard Knollb07f26b2019-03-07 09:55:3349 using ReadAllNotificationsCallback =
50 base::RepeatingCallback<void(const NotificationDatabaseData&)>;
Sharon Yangea520d82018-07-25 20:46:5351
Richard Knollb07f26b2019-03-07 09:55:3352 // Result status codes for interactions with the database. Will be used for
peter5bb2e1452015-03-12 15:31:1653 // UMA, so the assigned ids must remain stable.
54 enum Status {
55 STATUS_OK = 0,
56
peter513eb552015-03-16 18:55:0457 // The database, a notification, or a LevelDB key associated with the
58 // operation could not be found.
peter5bb2e1452015-03-12 15:31:1659 STATUS_ERROR_NOT_FOUND = 1,
60
61 // The database, or data in the database, could not be parsed as valid data.
62 STATUS_ERROR_CORRUPTED = 2,
63
64 // General failure code. More specific failures should be used if available.
65 STATUS_ERROR_FAILED = 3,
peter9684384a2015-04-01 17:23:5366
cmumford71054ce2015-10-20 17:15:4167 // leveldb failed due to I/O error (read-only, full disk, etc.).
68 STATUS_IO_ERROR = 4,
69
70 // leveldb operation not supported
71 STATUS_NOT_SUPPORTED = 5,
72
harknesse5646322016-06-22 08:56:2273 // Invalid database ID or snapshot ID provided.
74 STATUS_INVALID_ARGUMENT = 6,
75
peter9684384a2015-04-01 17:23:5376 // Number of entries in the status enumeration. Used by UMA. Must always be
77 // one higher than the otherwise highest value in this enumeration.
harknesse5646322016-06-22 08:56:2278 STATUS_COUNT = 7
peter5bb2e1452015-03-12 15:31:1679 };
80
Sharon Yangea520d82018-07-25 20:46:5381 NotificationDatabase(const base::FilePath& path, UkmCallback callback);
82
Peter Boström828b9022021-09-21 02:28:4383 NotificationDatabase(const NotificationDatabase&) = delete;
84 NotificationDatabase& operator=(const NotificationDatabase&) = delete;
85
peter5bb2e1452015-03-12 15:31:1686 ~NotificationDatabase();
87
88 // Opens the database. If |path| is non-empty, it will be created on the given
89 // directory on the filesystem. If |path| is empty, the database will be
90 // created in memory instead, and its lifetime will be tied to this instance.
91 // |create_if_missing| determines whether to create the database if necessary.
92 Status Open(bool create_if_missing);
93
peterc45944c32016-09-13 14:35:5994 // Gets the next assignable persistent notification ID. Subsequent calls to
95 // this method will yield unique identifiers for the same database. The last
96 // used ID will be written to the database when a notification is created.
97 int64_t GetNextPersistentNotificationId();
98
peter513eb552015-03-16 18:55:0499 // Reads the notification data for the notification identified by
100 // |notification_id| and belonging to |origin| from the database, and stores
peterc45944c32016-09-13 14:35:59101 // it in |*notification_data|. Returns the status code.
peter513eb552015-03-16 18:55:04102 Status ReadNotificationData(
peterc45944c32016-09-13 14:35:59103 const std::string& notification_id,
peter513eb552015-03-16 18:55:04104 const GURL& origin,
peterc45944c32016-09-13 14:35:59105 NotificationDatabaseData* notification_data) const;
peter513eb552015-03-16 18:55:04106
Richard Knoll2e136ef2019-03-07 09:45:11107 // Reads the notification resources for the notification identified by
108 // |notification_id| and belonging to |origin| from the database, and stores
109 // it in |*notification_resources|. Returns the status code.
110 Status ReadNotificationResources(
111 const std::string& notification_id,
112 const GURL& origin,
113 blink::NotificationResources* notification_resources) const;
114
Sharon Yangd96cd4b2018-05-31 11:43:43115 // This function is identical to ReadNotificationData above, but also records
116 // an interaction with that notification in the database for UKM logging
117 // purposes.
118 Status ReadNotificationDataAndRecordInteraction(
119 const std::string& notification_id,
120 const GURL& origin,
121 PlatformNotificationContext::Interaction interaction,
122 NotificationDatabaseData* notification_data);
123
Richard Knollb07f26b2019-03-07 09:55:33124 // Iterates over all notification data for all origins from the database, and
125 // calls |callback| with each notification data. Returns the status code.
126 Status ForEachNotificationData(ReadAllNotificationsCallback callback) const;
127
Richard Knoll25d3a8d2020-07-26 03:26:43128 // Iterates over all notification data for |service_worker_registration_id|
129 // belonging to |origin| from the database, and calls |callback| with each
130 // notification data. Returns the status code.
131 Status ForEachNotificationDataForServiceWorkerRegistration(
132 const GURL& origin,
133 int64_t service_worker_registration_id,
134 ReadAllNotificationsCallback callback) const;
peteradb2fe22015-03-19 18:49:28135
136 // Reads all notification data associated with |origin| from the database, and
137 // appends the data to |notification_data_vector|. Returns the status code.
138 Status ReadAllNotificationDataForOrigin(
139 const GURL& origin,
140 std::vector<NotificationDatabaseData>* notification_data_vector) const;
141
142 // Reads all notification data associated to |service_worker_registration_id|
143 // belonging to |origin| from the database, and appends the data to the
Richard Knoll5dcde8862021-07-16 14:38:56144 // |notification_data_vector|. Optionally filtered by |is_shown_by_browser|.
145 // Returns the status code.
peteradb2fe22015-03-19 18:49:28146 Status ReadAllNotificationDataForServiceWorkerRegistration(
147 const GURL& origin,
148 int64_t service_worker_registration_id,
Arthur Sonzognic686e8f2024-01-11 08:36:37149 std::optional<bool> is_shown_by_browser,
peteradb2fe22015-03-19 18:49:28150 std::vector<NotificationDatabaseData>* notification_data_vector) const;
151
peterc45944c32016-09-13 14:35:59152 // Writes the |notification_data| for a new notification belonging to |origin|
153 // to the database, and returns the status code of the writing operation. The
154 // notification's ID must have been set in the |notification_data|.
peter513eb552015-03-16 18:55:04155 Status WriteNotificationData(
156 const GURL& origin,
peterc45944c32016-09-13 14:35:59157 const NotificationDatabaseData& notification_data);
peter513eb552015-03-16 18:55:04158
159 // Deletes all data associated with the notification identified by
160 // |notification_id| belonging to |origin| from the database. Returns the
161 // status code of the deletion operation. Note that it is not considered a
162 // failure if the to-be-deleted notification does not exist.
peterc45944c32016-09-13 14:35:59163 Status DeleteNotificationData(const std::string& notification_id,
164 const GURL& origin);
peter05e061b2015-03-13 13:16:06165
Richard Knollacd400ea2019-05-31 11:53:07166 // Deletes resources associated with the notification identified by
167 // |notification_id| belonging to |origin| from the database. Returns the
168 // status code of the deletion operation. Note that it is not considered a
169 // failure if the to-be-deleted resources do not exist.
170 Status DeleteNotificationResources(const std::string& notification_id,
171 const GURL& origin);
172
peter3ce3c462016-08-09 16:23:58173 // Deletes all data associated with |origin| from the database, optionally
Richard Knoll5dcde8862021-07-16 14:38:56174 // filtered by |tag| and |is_shown_by_browser|, and appends the deleted
175 // notification ids to |deleted_notification_ids|. Returns the status code of
176 // the deletion operation.
peteradb2fe22015-03-19 18:49:28177 Status DeleteAllNotificationDataForOrigin(
178 const GURL& origin,
peter3ce3c462016-08-09 16:23:58179 const std::string& tag,
Arthur Sonzognic686e8f2024-01-11 08:36:37180 std::optional<bool> is_shown_by_browser,
peterc45944c32016-09-13 14:35:59181 std::set<std::string>* deleted_notification_ids);
peteradb2fe22015-03-19 18:49:28182
183 // Deletes all data associated with the |service_worker_registration_id|
184 // belonging to |origin| from the database, and appends the deleted
185 // notification ids to |deleted_notification_set|. Returns the status code
186 // of the deletion operation.
187 Status DeleteAllNotificationDataForServiceWorkerRegistration(
188 const GURL& origin,
189 int64_t service_worker_registration_id,
peterc45944c32016-09-13 14:35:59190 std::set<std::string>* deleted_notification_ids);
peteradb2fe22015-03-19 18:49:28191
peter5bb2e1452015-03-12 15:31:16192 // Completely destroys the contents of this database.
193 Status Destroy();
194
195 private:
196 friend class NotificationDatabaseTest;
197
Sharon Yange2decea2018-06-28 11:19:02198 enum class State {
199 UNINITIALIZED,
200 INITIALIZED,
201 DISABLED,
peter5bb2e1452015-03-12 15:31:16202 };
203
peterc45944c32016-09-13 14:35:59204 // Reads the next available persistent notification id from the database and
205 // returns the status code of the reading operation. The value will be stored
206 // in the |next_persistent_notification_id_| member.
207 Status ReadNextPersistentNotificationId();
peter05e061b2015-03-13 13:16:06208
Richard Knollb07f26b2019-03-07 09:55:33209 // Iterates over all notifications and pushes matching ones onto
210 // |notification_data_vector|. See ForEachNotificationDataInternal for deails.
211 Status ReadAllNotificationDataInternal(
212 const GURL& origin,
213 int64_t service_worker_registration_id,
Arthur Sonzognic686e8f2024-01-11 08:36:37214 std::optional<bool> is_shown_by_browser,
Richard Knollb07f26b2019-03-07 09:55:33215 std::vector<NotificationDatabaseData>* notification_data_vector) const;
216
peteradb2fe22015-03-19 18:49:28217 // Reads all notification data with the given constraints. |origin| may be
218 // empty to read all notification data from all origins. If |origin| is
219 // set, but |service_worker_registration_id| is invalid, then all notification
220 // data for |origin| will be read. If both are set, then all notification data
Richard Knoll5dcde8862021-07-16 14:38:56221 // for the given |service_worker_registration_id| will be read. If
Arthur Sonzognic686e8f2024-01-11 08:36:37222 // |is_shown_by_browser| is not std::nullopt, only notification data with
Richard Knoll5dcde8862021-07-16 14:38:56223 // matching |is_shown_by_browser| flags will be read.
Richard Knollb07f26b2019-03-07 09:55:33224 Status ForEachNotificationDataInternal(
peteradb2fe22015-03-19 18:49:28225 const GURL& origin,
226 int64_t service_worker_registration_id,
Arthur Sonzognic686e8f2024-01-11 08:36:37227 std::optional<bool> is_shown_by_browser,
Richard Knollb07f26b2019-03-07 09:55:33228 ReadAllNotificationsCallback callback) const;
peteradb2fe22015-03-19 18:49:28229
230 // Deletes all notification data with the given constraints. |origin| must
231 // always be set - use Destroy() when the goal is to empty the database. If
232 // |service_worker_registration_id| is invalid, all notification data for the
Richard Knoll5dcde8862021-07-16 14:38:56233 // |origin| will be deleted, optionally filtered by |tag| and
234 // |is_shown_by_browser| when non-empty. All deleted notification ids will be
235 // written to |deleted_notification_ids|.
peteradb2fe22015-03-19 18:49:28236 Status DeleteAllNotificationDataInternal(
237 const GURL& origin,
peter3ce3c462016-08-09 16:23:58238 const std::string& tag,
Arthur Sonzognic686e8f2024-01-11 08:36:37239 std::optional<bool> is_shown_by_browser,
peteradb2fe22015-03-19 18:49:28240 int64_t service_worker_registration_id,
peterc45944c32016-09-13 14:35:59241 std::set<std::string>* deleted_notification_ids);
peteradb2fe22015-03-19 18:49:28242
peter5bb2e1452015-03-12 15:31:16243 // Returns whether the database has been opened.
244 bool IsOpen() const { return db_ != nullptr; }
245
246 // Returns whether the database should only exist in memory.
247 bool IsInMemoryDatabase() const { return path_.empty(); }
248
peter05e061b2015-03-13 13:16:06249 // Exposes the LevelDB database used to back this notification database.
250 // Should only be used for testing purposes.
251 leveldb::DB* GetDBForTesting() const { return db_.get(); }
252
peter5bb2e1452015-03-12 15:31:16253 base::FilePath path_;
254
dcheng59716272016-04-09 05:19:08255 std::unique_ptr<const leveldb::FilterPolicy> filter_policy_;
peterc1978f942015-04-01 17:38:18256
peter5bb2e1452015-03-12 15:31:16257 // The declaration order for these members matters, as |db_| depends on |env_|
258 // and thus has to be destructed first.
dcheng59716272016-04-09 05:19:08259 std::unique_ptr<leveldb::Env> env_;
260 std::unique_ptr<leveldb::DB> db_;
peter5bb2e1452015-03-12 15:31:16261
Sharon Yange2decea2018-06-28 11:19:02262 State state_ = State::UNINITIALIZED;
peter5bb2e1452015-03-12 15:31:16263
Christian Flacha80f17b2022-09-12 19:05:59264 SEQUENCE_CHECKER(sequence_checker_);
peter5bb2e1452015-03-12 15:31:16265
Sharon Yangea520d82018-07-25 20:46:53266 // Callback to use for recording UKM metrics. Must be posted to the UI thread.
267 UkmCallback record_notification_to_ukm_callback_;
peter5bb2e1452015-03-12 15:31:16268};
269
270} // namespace content
271
272#endif // CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_DATABASE_H_