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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
content / browser / notifications / platform_notification_context_impl.h [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_CONTEXT_IMPL_H_
#define CONTENT_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_CONTEXT_IMPL_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "content/browser/notifications/notification_database.h"
#include "content/browser/notifications/notification_id_generator.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/platform_notification_context.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
class GURL;
namespace base {
class SequencedTaskRunner;
}
namespace blink {
class StorageKey;
} // namespace blink
namespace content {
class BlinkNotificationServiceImpl;
class BrowserContext;
struct NotificationDatabaseData;
class PlatformNotificationServiceProxy;
class RenderProcessHost;
class ServiceWorkerContextWrapper;
class WeakDocumentPtr;
// Implementation of the Web Notification storage context. The public methods
// defined in this interface must only be called on the UI thread.
class CONTENT_EXPORT PlatformNotificationContextImpl
: public PlatformNotificationContext,
public ServiceWorkerContextCoreObserver {
public:
// Constructs a new platform notification context. If |path| is non-empty, the
// database will be initialized in the "Platform Notifications" subdirectory
// of |path|. Otherwise, the database will be initialized in memory.
PlatformNotificationContextImpl(
const base::FilePath& path,
BrowserContext* browser_context,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
PlatformNotificationContextImpl(const PlatformNotificationContextImpl&) =
delete;
PlatformNotificationContextImpl& operator=(
const PlatformNotificationContextImpl&) = delete;
// To be called to initialize the instance.
void Initialize();
// To be called when the context is being shut down.
void Shutdown();
// Creates a BlinkNotificationServiceImpl that is owned by this context.
// The `document_url` will be empty if the service is created by a worker.
// The `weak_document_ptr` points to the document if it's the creator of the
// notification service, or the worker's ancestor document if the notification
// service is created by a dedicated worker, or is `nullptr` otherwise.
void CreateService(
RenderProcessHost* render_process_host,
const blink::StorageKey& storage_key,
const GURL& document_url,
const WeakDocumentPtr& weak_document_ptr,
const RenderProcessHost::NotificationServiceCreatorType creator_type,
mojo::PendingReceiver<blink::mojom::NotificationService> receiver);
// Removes |service| from the list of owned services, for example because the
// Mojo pipe disconnected. Must be called on the UI thread.
void RemoveService(BlinkNotificationServiceImpl* service);
// Returns the notification Id generator owned by the context.
NotificationIdGenerator* notification_id_generator() {
return ¬ification_id_generator_;
}
// PlatformNotificationContext implementation.
void ReadNotificationDataAndRecordInteraction(
const std::string& notification_id,
const GURL& origin,
Interaction interaction,
ReadResultCallback callback) override;
void ReadNotificationResources(const std::string& notification_id,
const GURL& origin,
ReadResourcesResultCallback callback) override;
void WriteNotificationData(int64_t persistent_notification_id,
int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
WriteResultCallback callback) override;
void DeleteNotificationData(const std::string& notification_id,
const GURL& origin,
bool close_notification,
DeleteResultCallback callback) override;
void DeleteAllNotificationDataWithTag(
const std::string& tag,
std::optional<bool> is_shown_by_browser,
const GURL& origin,
DeleteAllResultCallback callback) override;
void DeleteAllNotificationDataForBlockedOrigins(
DeleteAllResultCallback callback) override;
void ReadAllNotificationDataForServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
ReadAllResultCallback callback) override;
void CountVisibleNotificationsForServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
CountResultCallback callback) override;
void TriggerNotifications() override;
void WriteNotificationResources(
std::vector<NotificationResourceData> resource_data,
WriteResourcesResultCallback callback) override;
void ReDisplayNotifications(
std::vector<GURL> origins,
ReDisplayNotificationsResultCallback callback) override;
// ServiceWorkerContextCoreObserver implementation.
void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern,
const blink::StorageKey& key) override;
void OnStorageWiped() override;
private:
friend class PlatformNotificationContextTest;
friend class PlatformNotificationContextTriggerTest;
~PlatformNotificationContextImpl() override;
void DidGetNotifications(std::set<std::string> displayed_notifications,
bool supports_synchronization);
using InitializeResultCallback = base::OnceCallback<void(bool)>;
using ReadAllOriginsResultCallback =
base::OnceCallback<void(bool /* success */,
std::set<GURL> /* origins */)>;
using InitializeGetDisplayedCallback = base::OnceCallback<void(
std::set<std::string> /* displayed_notifications */,
bool /* supports_synchronization */,
bool /* initialized */)>;
// Initializes the database if necessary. |callback| will be invoked on the
// |task_runner_| thread. If |lazy| is true this will not try to create a new
// database if there isn't one already. Otherwise this will try to open or
// create a new database. If everything is available, |callback| will be
// called with true, otherwise it will be called with false.
void InitializeDatabase(InitializeResultCallback callback, bool lazy = false);
// Marks this notification as shown and displays it.
void DoTriggerNotification(const NotificationDatabaseData& database_data);
// Opens the database. Must be called on the |task_runner_| thread. |callback|
// will be invoked on the |task_runner_| thread. If |create_if_missing| is
// true this will try to create a new database if there isn't one already.
// Otherwise we will just try to open it. When the database has been
// successfully opened, |callback| will be called with true, otherwise it will
// be called with false.
void OpenDatabase(InitializeResultCallback callback, bool create_if_missing);
// Actually reads the notification data from the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the
// UI thread when the operation has completed.
void DoReadNotificationData(const std::string& notification_id,
const GURL& origin,
Interaction interaction,
ReadResultCallback callback,
bool initialized);
// Actually reads the notification resources from the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the
// UI thread when the operation has completed.
void DoReadNotificationResources(const std::string& notification_id,
const GURL& origin,
ReadResourcesResultCallback callback,
bool initialized);
// Synchronize displayed notifications. This removes all non-displayed
// notifications from the database.
void DoSyncNotificationData(bool supports_synchronization,
std::set<std::string> displayed_notifications,
bool initialized);
// Checks if the given notification is still valid, otherwise deletes it from
// the database. Fills |close_notification_ids| with notification ids that
// should be closed by the platform.
void DoHandleSyncNotification(
bool supports_synchronization,
const std::set<std::string>& displayed_notifications,
std::set<std::string>* close_notification_ids,
const NotificationDatabaseData& data);
// Tries to get a list of displayed notification ids for `origin` if the
// platform supports synchronizing them. Calls `callback` with the result
// after initializing the database on the `task_runner_` thread.
void TryGetDisplayedNotifications(const GURL& origin,
InitializeGetDisplayedCallback callback);
// Called after getting a list of |displayed_notifications| on the UI thread.
// Calls |callback| after initializing the database on the |task_runner_|
// thread.
void OnGetDisplayedNotifications(
InitializeGetDisplayedCallback callback,
std::set<std::string> displayed_notifications,
bool supports_synchronization);
// Actually reads all notification data from the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the
// UI thread when the operation has completed.
void DoReadAllNotificationDataForServiceWorkerRegistration(
base::Time start_time,
const GURL& origin,
int64_t service_worker_registration_id,
ReadAllResultCallback callback,
std::set<std::string> displayed_notifications,
bool supports_synchronization,
bool initialized);
// Actually counts visible notifications for |service_worker_registration_id|
// by comparing the entries in the database with |displayed_notifications|.
// Must only be called on the |task_runner_| thread. |callback| will be
// invoked on the UI thread when the operation has completed.
void DoCountVisibleNotificationsForServiceWorkerRegistration(
base::Time start_time,
const GURL& origin,
int64_t service_worker_registration_id,
CountResultCallback callback,
std::set<std::string> displayed_notifications,
bool supports_synchronization,
bool initialized);
// Checks if the number of notifications scheduled for |origin| does not
// exceed the quota.
bool DoCheckNotificationTriggerQuota(const GURL& origin);
// Actually writes the notification database to the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the
// UI thread when the operation has completed.
void DoWriteNotificationData(int64_t persistent_notification_id,
int64_t service_worker_registration_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
WriteResultCallback callback,
bool initialized);
// Actually deletes the notification information from the database. Must only
// be called on the |task_runner_| thread. |callback| will be invoked on the
// UI thread when the operation has completed.
void DoDeleteNotificationData(const std::string& notification_id,
const GURL& origin,
DeleteResultCallback callback,
bool should_log_close,
bool initialized);
// Actually reads all notification origins from the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the UI
// thread when the operation has completed.
void DoReadAllNotificationOrigins(ReadAllOriginsResultCallback callback,
bool initialized);
// Checks permissions for all |origins| via PermissionController and deletes
// all notifications for origins that do not have granted permissions. Must be
// called on the UI thread. |callback| will be invoked on the UI thread when
// the operation has completed.
void CheckPermissionsAndDeleteBlocked(DeleteAllResultCallback callback,
bool success,
std::set<GURL> origins);
// Actually deletes the notification information for all |origins| from the
// database. Optionally filtered by |tag|. Must only be called on the
// |task_runner_| thread. |callback| will be invoked on the UI thread when the
// operation has completed.
void DoDeleteAllNotificationDataForOrigins(
std::set<GURL> origins,
const std::string& tag,
std::optional<bool> is_shown_by_browser,
DeleteAllResultCallback callback,
bool initialized);
// Actually writes the notification resources to the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the UI
// thread when the operation has completed.
void DoWriteNotificationResources(
std::vector<NotificationResourceData> resource_data,
WriteResourcesResultCallback callback,
bool initialized);
// Actually reads all notification that should be on screen for |origins| from
// the database and displays them. Must only be called on the |task_runner_|
// thread. |callback| will be invoked on the UI thread with the number of
// displayed notifications when the operation has completed.
void DoReDisplayNotifications(std::vector<GURL> origins,
ReDisplayNotificationsResultCallback callback,
bool initialized);
void OnStorageWipedInitialized(bool initialized);
// Deletes all notifications associated with |service_worker_registration_id|
// belonging to |origin|. Must be called on the |task_runner_| thread.
void DoDeleteNotificationsForServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
bool initialized);
// Destroys the database regardless of its initialization status. This method
// must only be called on the |task_runner_| thread. Returns if the directory
// the database was stored in could be emptied.
bool DestroyDatabase();
// Returns the path in which the database should be initialized. May be empty.
base::FilePath GetDatabasePath() const;
// Sets the task runner to use for testing purposes.
void SetTaskRunnerForTesting(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
void DisplayNotification(const NotificationDatabaseData& data,
WriteResultCallback callback);
void CloseNotifications(const std::set<std::string>& notification_ids);
void ScheduleTrigger(base::Time timestamp);
void ScheduleNotification(const NotificationDatabaseData& data);
void LogClose(const NotificationDatabaseData& data);
base::FilePath path_;
raw_ptr<BrowserContext> browser_context_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<NotificationDatabase> database_;
NotificationIdGenerator notification_id_generator_;
// Keeps track of the next trigger timestamp.
std::optional<base::Time> next_trigger_;
// Calls through to PlatformNotificationService methods.
std::unique_ptr<PlatformNotificationServiceProxy> service_proxy_;
// The notification services are owned by the platform context, and will be
// removed when either this class is destroyed or the Mojo pipe disconnects.
std::vector<std::unique_ptr<BlinkNotificationServiceImpl>> services_;
NotificationDatabase::UkmCallback ukm_callback_;
// Flag if the |browser_context_| has been shutdown already.
std::atomic_bool has_shutdown_;
};
} // namespace content
#endif // CONTENT_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_CONTEXT_IMPL_H_