blob: 231a266a4c8d8a729baa701c47cb19348e199f79 [file] [log] [blame]
// Copyright 2014 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_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_
#define CHROME_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <unordered_set>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/notifications/notification_common.h"
#include "chrome/browser/notifications/notification_trigger_scheduler.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/buildflags.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/platform_notification_service.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/message_center/public/cpp/notification.h"
class GURL;
class Profile;
namespace blink {
struct NotificationResources;
} // namespace blink
// The platform notification service is the profile-specific entry point through
// which Web Notifications can be controlled.
class PlatformNotificationServiceImpl
: public content::PlatformNotificationService,
public content_settings::Observer,
public KeyedService {
public:
explicit PlatformNotificationServiceImpl(Profile* profile);
PlatformNotificationServiceImpl(const PlatformNotificationServiceImpl&) =
delete;
PlatformNotificationServiceImpl& operator=(
const PlatformNotificationServiceImpl&) = delete;
~PlatformNotificationServiceImpl() override;
// Register profile-specific prefs.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Returns whether the notification identified by |notification_id| was
// closed programmatically through ClosePersistentNotification().
bool WasClosedProgrammatically(const std::string& notification_id);
// content::PlatformNotificationService implementation.
void DisplayNotification(
const std::string& notification_id,
const GURL& origin,
const GURL& document_url,
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources) override;
void DisplayPersistentNotification(
const std::string& notification_id,
const GURL& service_worker_scope,
const GURL& origin,
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources) override;
void CloseNotification(const std::string& notification_id) override;
void ClosePersistentNotification(const std::string& notification_id) override;
void GetDisplayedNotifications(
DisplayedNotificationsCallback callback) override;
void GetDisplayedNotificationsForOrigin(
const GURL& origin,
DisplayedNotificationsCallback callback) override;
void ScheduleTrigger(base::Time timestamp) override;
base::Time ReadNextTriggerTimestamp() override;
int64_t ReadNextPersistentNotificationId() override;
void RecordNotificationUkmEvent(
const content::NotificationDatabaseData& data) override;
void set_ukm_recorded_closure_for_testing(base::OnceClosure closure) {
ukm_recorded_closure_for_testing_ = std::move(closure);
}
NotificationTriggerScheduler* GetNotificationTriggerScheduler();
private:
friend class NotificationTriggerSchedulerTest;
friend class PersistentNotificationHandlerTest;
friend class PlatformNotificationServiceBrowserTest;
friend class PlatformNotificationServiceTest;
friend class PushMessagingBrowserTest;
FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest,
CreateNotificationFromData);
FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest,
DisplayNameForContextMessage);
FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest,
RecordNotificationUkmEvent);
FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest, IncomingCallWebApp);
FRIEND_TEST_ALL_PREFIXES(
PlatformNotificationServiceTest_WebAppNotificationIconAndTitle,
FindWebAppIconAndTitle_NoApp);
FRIEND_TEST_ALL_PREFIXES(
PlatformNotificationServiceTest_WebAppNotificationIconAndTitle,
FindWebAppIconAndTitle);
struct WebAppIconAndTitle {
gfx::ImageSkia icon;
std::u16string title;
};
// KeyedService implementation.
void Shutdown() override;
// content_settings::Observer implementation.
void OnContentSettingChanged(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsTypeSet content_type_set) override;
static void RecordNotificationUkmEventWithSourceId(
base::OnceClosure recorded_closure,
const content::NotificationDatabaseData& data,
ukm::SourceId source_id);
// Creates a new Web Notification-based Notification object. Should only be
// called when the notification is first shown. |web_app_hint_url| is used to
// find a corresponding web app, it can be a service worker scope or document
// url.
message_center::Notification CreateNotificationFromData(
const GURL& origin,
const std::string& notification_id,
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources,
const GURL& web_app_hint_url) const;
// Returns a display name for an origin, to be used in the context message
std::u16string DisplayNameForContextMessage(const GURL& origin) const;
// Finds the AppId associated with |web_app_hint_url| when this is part of
// an installed experience, and the notification can be attributed as such.
std::optional<webapps::AppId> FindWebAppId(
const GURL& web_app_hint_url) const;
// Finds the icon and title associated with |web_app_id| when this
// is part of an installed experience, and the notification can be attributed
// as such.
std::optional<WebAppIconAndTitle> FindWebAppIconAndTitle(
const GURL& web_app_hint_url) const;
// Identifies whether the notification was sent from an installed web app or
// not.
bool IsActivelyInstalledWebAppScope(const GURL& web_app_url) const;
// Clears |closed_notifications_|. Should only be used for testing purposes.
void ClearClosedNotificationsForTesting() { closed_notifications_.clear(); }
// The profile for this instance or NULL if the initial profile has been
// shutdown already.
raw_ptr<Profile> profile_;
// Tracks the id of persistent notifications that have been closed
// programmatically to avoid dispatching close events for them.
std::unordered_set<std::string> closed_notifications_;
// Scheduler for notifications with a trigger.
std::unique_ptr<NotificationTriggerScheduler> trigger_scheduler_;
// Testing-only closure to observe when a UKM event has been recorded.
base::OnceClosure ukm_recorded_closure_for_testing_;
};
#endif // CHROME_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_