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
|
// Copyright 2016 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_NOTIFICATIONS_PERSISTENT_NOTIFICATION_HANDLER_H_
#define CHROME_BROWSER_NOTIFICATIONS_PERSISTENT_NOTIFICATION_HANDLER_H_
#include <map>
#include <memory>
#include "base/callback_list.h"
#include "base/containers/id_map.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/notifications/notification_handler.h"
#include "chrome/common/buildflags.h"
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE)
class ScopedKeepAlive;
class ScopedProfileKeepAlive;
namespace content {
enum class PersistentNotificationStatus;
} // namespace content
// NotificationHandler implementation for persistent Web Notifications, that is,
// notifications associated with a Service Worker. Lives on the UI thread.
class PersistentNotificationHandler : public NotificationHandler {
public:
PersistentNotificationHandler();
PersistentNotificationHandler(const PersistentNotificationHandler&) = delete;
PersistentNotificationHandler& operator=(
const PersistentNotificationHandler&) = delete;
~PersistentNotificationHandler() override;
// NotificationHandler implementation.
void OnClose(Profile* profile,
const GURL& origin,
const std::string& notification_id,
bool by_user,
base::OnceClosure completed_closure) override;
void OnClick(Profile* profile,
const GURL& origin,
const std::string& notification_id,
const std::optional<int>& action_index,
const std::optional<std::u16string>& reply,
base::OnceClosure completed_closure) override;
void DisableNotifications(Profile* profile, const GURL& origin) override;
void OpenSettings(Profile* profile, const GURL& origin) override;
void ReportNotificationAsSafe(const std::string& notification_id,
const GURL& url,
Profile* profile) override;
void ReportWarnedNotificationAsSpam(const std::string& notification_id,
const GURL& url,
Profile* profile) override;
void ReportUnwarnedNotificationAsSpam(const std::string& notification_id,
const GURL& url,
Profile* profile) override;
private:
void OnCloseCompleted(Profile* profile,
uint64_t close_completed_callback_id,
content::PersistentNotificationStatus status);
void OnClickCompleted(Profile* profile,
const std::string& notification_id,
base::OnceClosure completed_closure,
content::PersistentNotificationStatus status);
void OnMaybeReport(const std::string& notification_id,
const GURL& url,
Profile* profile,
bool did_show_warning,
bool did_user_unsubscribe);
void OnAppTerminating();
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
class NotificationKeepAliveState {
public:
NotificationKeepAliveState(
KeepAliveOrigin keep_alive_origin,
ProfileKeepAliveOrigin profile_keep_alive_origin);
~NotificationKeepAliveState();
void AddKeepAlive(Profile* profile);
void RemoveKeepAlive(Profile* profile);
void RemoveAllKeepAlives();
private:
const KeepAliveOrigin keep_alive_origin_;
const ProfileKeepAliveOrigin profile_keep_alive_origin_;
// Makes sure we keep the browser alive while the event in being processed.
// As we have no control on the click handling, the notification could be
// closed before a browser is brought up, thus terminating Chrome if it was
// the last KeepAlive (see crbug.com/612815). We also need to wait until
// close events got handled as we need to access the profile when removing
// notifications from the NotificationDatabase (see crbug.com/1221601).
std::unique_ptr<ScopedKeepAlive> event_dispatch_keep_alive_;
// Same as |event_dispatch_keep_alive_|, but prevent Profile* deletion
// instead of BrowserProcess teardown.
std::map<Profile*, std::unique_ptr<ScopedProfileKeepAlive>>
event_dispatch_profile_keep_alives_;
// Number of in-flight notification events.
int pending_dispatch_events_ = 0;
// Number of in-flight notification events per Profile, for
// |event_dispatch_profile_keep_alives_|.
std::map<Profile*, int> profile_pending_dispatch_events_;
};
NotificationKeepAliveState click_event_keep_alive_state_{
KeepAliveOrigin::PENDING_NOTIFICATION_CLICK_EVENT,
ProfileKeepAliveOrigin::kPendingNotificationClickEvent};
NotificationKeepAliveState close_event_keep_alive_state_{
KeepAliveOrigin::PENDING_NOTIFICATION_CLOSE_EVENT,
ProfileKeepAliveOrigin::kPendingNotificationCloseEvent};
#endif
// App termination must release all `PENDING_NOTIFICATION_CLOSE_EVENT` keep
// alives to avoid delaying shutdown. After app termination begins, a new
// browser launch cannot create a new window until shutdown completes.
base::CallbackListSubscription on_app_terminating_subscription_;
// Store pending 'notificationclose' event callbacks. App termination may
// run these callbacks before the 'notificationclose' event completes.
using CloseCompletedCallbackMap =
base::IDMap<std::unique_ptr<base::OnceClosure>>;
CloseCompletedCallbackMap close_completed_callbacks_;
base::WeakPtrFactory<PersistentNotificationHandler> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_NOTIFICATIONS_PERSISTENT_NOTIFICATION_HANDLER_H_
|