#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
#include <map>
#include <sstream>
#include <vector>
#include "base/barrier_closure.h"
#include "base/base64url.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/gcm/gcm_profile_service_factory.h"
#include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h"
#include "chrome/browser/lifetime/termination_notification.h"
#include "chrome/browser/permissions/permission_revocation_request.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
#include "chrome/browser/push_messaging/push_messaging_constants.h"
#include "chrome/browser/push_messaging/push_messaging_features.h"
#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
#include "chrome/browser/push_messaging/push_messaging_utils.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/gcm_driver/gcm_driver.h"
#include "components/gcm_driver/gcm_profile_service.h"
#include "components/gcm_driver/instance_id/instance_id.h"
#include "components/gcm_driver/instance_id/instance_id_driver.h"
#include "components/gcm_driver/instance_id/instance_id_profile_service.h"
#include "components/permissions/permission_manager.h"
#include "components/permissions/permission_uma_util.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/devtools_background_services_context.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "extensions/common/constants.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
#include "chrome/browser/background/background_mode_manager.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "chrome/android/chrome_jni_headers/PushMessagingServiceBridge_jni.h"
#include "chrome/android/chrome_jni_headers/PushMessagingServiceObserver_jni.h"
#include "chrome/browser/android/shortcut_helper.h"
#include "chrome/browser/notifications/notification_platform_bridge.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "components/permissions/android/android_permission_util.h"
#endif
#if BUILDFLAG(IS_ANDROID)
using base::android::ConvertJavaStringToUTF8;
using base::android::JavaParamRef;
#endif
InstanceID;
namespace {
const char kGCMScope[] = …;
const int kMaxRegistrations = …;
const char kSilentPushUnsupportedMessage[] = …;
const char kSenderIdRegistrationDisallowedMessage[] = …;
const char kSenderIdRegistrationDeprecatedMessage[] = …;
#if BUILDFLAG(IS_ANDROID)
const char kNotificationsPermissionRevocationGracePeriodDate[] =
"notifications_permission_revocation_grace_period";
int GetNotificationsRevocationGracePeriodInDays() {
return base::GetFieldTrialParamByFeatureAsInt(
features::kRevokeNotificationsPermissionIfDisabledOnAppLevel,
features::kNotificationRevocationGracePeriodInDays, 3);
}
#endif
void RecordDeliveryStatus(blink::mojom::PushEventStatus status) { … }
void RecordUnsubscribeReason(blink::mojom::PushUnregistrationReason reason) { … }
void UnregisterCallbackToClosure(
base::OnceClosure closure,
blink::mojom::PushUnregistrationStatus status) { … }
void LogMessageReceivedEventToDevTools(
content::DevToolsBackgroundServicesContext* devtools_context,
const PushMessagingAppIdentifier& app_identifier,
const std::string& message_id,
bool was_encrypted,
const std::string& error_message,
const std::string& payload) { … }
PendingMessage::PendingMessage(std::string app_id, gcm::IncomingMessage message)
: … { … }
PendingMessage::PendingMessage(const PendingMessage& other) = default;
PendingMessage::PendingMessage(PendingMessage&& other) = default;
PendingMessage& PendingMessage::operator=(PendingMessage&& other) = default;
PendingMessage::~PendingMessage() = default;
}
void PushMessagingServiceImpl::InitializeForProfile(Profile* profile) { … }
void PushMessagingServiceImpl::RemoveExpiredSubscriptions() { … }
void PushMessagingServiceImpl::UnexpectedChange(
PushMessagingAppIdentifier identifier,
blink::mojom::PushUnregistrationReason reason,
base::OnceClosure completed_closure) { … }
PushMessagingServiceImpl::PushMessagingServiceImpl(Profile* profile)
: … { … }
PushMessagingServiceImpl::~PushMessagingServiceImpl() = default;
void PushMessagingServiceImpl::IncreasePushSubscriptionCount(int add,
bool is_pending) { … }
void PushMessagingServiceImpl::DecreasePushSubscriptionCount(int subtract,
bool was_pending) { … }
bool PushMessagingServiceImpl::CanHandle(const std::string& app_id) const { … }
void PushMessagingServiceImpl::ShutdownHandler() { … }
void PushMessagingServiceImpl::OnStoreReset() { … }
void PushMessagingServiceImpl::OnMessage(const std::string& app_id,
const gcm::IncomingMessage& message) { … }
void PushMessagingServiceImpl::CheckOriginAndDispatchNextMessage() { … }
void PushMessagingServiceImpl::OnCheckedOrigin(
PendingMessage message,
PermissionRevocationRequest::Outcome outcome) { … }
void PushMessagingServiceImpl::
DeliverNextQueuedMessageForServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id) { … }
void PushMessagingServiceImpl::DeliverMessageCallback(
const std::string& app_id,
const GURL& requesting_origin,
int64_t service_worker_registration_id,
const gcm::IncomingMessage& message,
bool did_enqueue_message,
blink::mojom::PushEventStatus status) { … }
void PushMessagingServiceImpl::DidHandleEnqueuedMessage(
const GURL& origin,
int64_t service_worker_registration_id,
base::OnceCallback<void(bool)> message_handled_callback,
bool did_show_generic_notification) { … }
void PushMessagingServiceImpl::DidHandleMessage(
const std::string& app_id,
const std::string& push_message_id,
bool did_show_generic_notification) { … }
void PushMessagingServiceImpl::SetMessageCallbackForTesting(
const base::RepeatingClosure& callback) { … }
void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) { … }
void PushMessagingServiceImpl::OnSendError(
const std::string& app_id,
const gcm::GCMClient::SendErrorDetails& send_error_details) { … }
void PushMessagingServiceImpl::OnSendAcknowledged(
const std::string& app_id,
const std::string& message_id) { … }
void PushMessagingServiceImpl::OnMessageDecryptionFailed(
const std::string& app_id,
const std::string& message_id,
const std::string& error_message) { … }
void PushMessagingServiceImpl::SubscribeFromDocument(
const GURL& requesting_origin,
int64_t service_worker_registration_id,
int render_process_id,
int render_frame_id,
blink::mojom::PushSubscriptionOptionsPtr options,
bool user_gesture,
RegisterCallback callback) { … }
void PushMessagingServiceImpl::SubscribeFromWorker(
const GURL& requesting_origin,
int64_t service_worker_registration_id,
int render_process_id,
blink::mojom::PushSubscriptionOptionsPtr options,
RegisterCallback register_callback) { … }
blink::mojom::PermissionStatus PushMessagingServiceImpl::GetPermissionStatus(
const GURL& origin,
bool user_visible) { … }
#if BUILDFLAG(IS_ANDROID)
void PushMessagingServiceImpl::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterTimePref(kNotificationsPermissionRevocationGracePeriodDate,
base::Time());
}
static void
JNI_PushMessagingServiceBridge_VerifyAndRevokeNotificationsPermission(
JNIEnv* env,
std::string& origin,
std::string& profile_id,
jboolean app_level_notifications_enabled) {
if (!base::FeatureList::IsEnabled(
features::kRevokeNotificationsPermissionIfDisabledOnAppLevel)) {
return;
}
ProfileManager* profile_manager = g_browser_process->profile_manager();
DCHECK(profile_manager);
profile_manager->LoadProfile(
NotificationPlatformBridge::GetProfileBaseNameFromProfileId(profile_id),
false,
base::BindOnce(&PushMessagingServiceImpl::RevokePermissionIfPossible,
GURL(origin), app_level_notifications_enabled,
g_browser_process->local_state()));
}
void PushMessagingServiceImpl::RevokePermissionIfPossible(
GURL origin,
bool app_level_notifications_enabled,
PrefService* prefs,
Profile* profile) {
if (app_level_notifications_enabled) {
prefs->ClearPref(kNotificationsPermissionRevocationGracePeriodDate);
return;
}
if (prefs->GetTime(kNotificationsPermissionRevocationGracePeriodDate) ==
base::Time()) {
prefs->SetTime(kNotificationsPermissionRevocationGracePeriodDate,
base::Time::Now());
return;
}
base::TimeDelta permission_revocation_activated_duration =
base::Time::Now() -
prefs->GetTime(kNotificationsPermissionRevocationGracePeriodDate);
if (permission_revocation_activated_duration.InDays() >=
GetNotificationsRevocationGracePeriodInDays()) {
content::PermissionController* permission_controller =
profile->GetPermissionController();
permission_controller->ResetPermission(blink::PermissionType::NOTIFICATIONS,
url::Origin::Create(origin));
}
}
#endif
bool PushMessagingServiceImpl::SupportNonVisibleMessages() { … }
void PushMessagingServiceImpl::DoSubscribe(
PushMessagingAppIdentifier app_identifier,
blink::mojom::PushSubscriptionOptionsPtr options,
RegisterCallback register_callback,
int render_process_id,
int render_frame_id,
blink::mojom::PermissionStatus permission_status) { … }
void PushMessagingServiceImpl::SubscribeEnd(
RegisterCallback callback,
const std::string& subscription_id,
const GURL& endpoint,
const std::optional<base::Time>& expiration_time,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
blink::mojom::PushRegistrationStatus status) { … }
void PushMessagingServiceImpl::SubscribeEndWithError(
RegisterCallback callback,
blink::mojom::PushRegistrationStatus status) { … }
void PushMessagingServiceImpl::DidSubscribe(
const PushMessagingAppIdentifier& app_identifier,
const std::string& sender_id,
RegisterCallback callback,
const std::string& subscription_id,
InstanceID::Result result) { … }
void PushMessagingServiceImpl::DidSubscribeWithEncryptionInfo(
const PushMessagingAppIdentifier& app_identifier,
RegisterCallback callback,
const std::string& subscription_id,
const GURL& endpoint,
std::string p256dh,
std::string auth_secret) { … }
void PushMessagingServiceImpl::GetSubscriptionInfo(
const GURL& origin,
int64_t service_worker_registration_id,
const std::string& sender_id,
const std::string& subscription_id,
SubscriptionInfoCallback callback) { … }
void PushMessagingServiceImpl::DidValidateSubscription(
const std::string& app_id,
const std::string& sender_id,
const GURL& endpoint,
const std::optional<base::Time>& expiration_time,
SubscriptionInfoCallback callback,
bool is_valid) { … }
void PushMessagingServiceImpl::DidGetEncryptionInfo(
const GURL& endpoint,
const std::optional<base::Time>& expiration_time,
SubscriptionInfoCallback callback,
std::string p256dh,
std::string auth_secret) const { … }
void PushMessagingServiceImpl::Unsubscribe(
blink::mojom::PushUnregistrationReason reason,
const GURL& requesting_origin,
int64_t service_worker_registration_id,
const std::string& sender_id,
UnregisterCallback callback) { … }
void PushMessagingServiceImpl::UnsubscribeInternal(
blink::mojom::PushUnregistrationReason reason,
const GURL& origin,
int64_t service_worker_registration_id,
const std::string& app_id,
const std::string& sender_id,
UnregisterCallback callback) { … }
void PushMessagingServiceImpl::DidClearPushSubscriptionId(
blink::mojom::PushUnregistrationReason reason,
const std::string& app_id,
const std::string& sender_id,
UnregisterCallback callback) { … }
void PushMessagingServiceImpl::DidUnregister(bool was_subscribed,
gcm::GCMClient::Result result) { … }
void PushMessagingServiceImpl::DidDeleteID(const std::string& app_id,
bool was_subscribed,
InstanceID::Result result) { … }
void PushMessagingServiceImpl::DidUnsubscribe(
const std::string& app_id_when_instance_id,
bool was_subscribed) { … }
void PushMessagingServiceImpl::SetUnsubscribeCallbackForTesting(
base::OnceClosure callback) { … }
void PushMessagingServiceImpl::DidDeleteServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id) { … }
void PushMessagingServiceImpl::SetServiceWorkerUnregisteredCallbackForTesting(
base::RepeatingClosure callback) { … }
void PushMessagingServiceImpl::DidDeleteServiceWorkerDatabase() { … }
void PushMessagingServiceImpl::SetServiceWorkerDatabaseWipedCallbackForTesting(
base::RepeatingClosure callback) { … }
void PushMessagingServiceImpl::OnContentSettingChanged(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsTypeSet content_type_set) { … }
void PushMessagingServiceImpl::UnexpectedUnsubscribe(
const PushMessagingAppIdentifier& app_identifier,
blink::mojom::PushUnregistrationReason reason,
UnregisterCallback unregister_callback) { … }
void PushMessagingServiceImpl::GetPushSubscriptionFromAppIdentifier(
const PushMessagingAppIdentifier& app_identifier,
base::OnceCallback<void(blink::mojom::PushSubscriptionPtr)>
subscription_cb) { … }
void PushMessagingServiceImpl::DidGetSWData(
const PushMessagingAppIdentifier& app_identifier,
base::OnceCallback<void(blink::mojom::PushSubscriptionPtr)> subscription_cb,
const std::string& sender_id,
const std::string& subscription_id) { … }
void PushMessagingServiceImpl::GetPushSubscriptionFromAppIdentifierEnd(
base::OnceCallback<void(blink::mojom::PushSubscriptionPtr)> callback,
const std::string& sender_id,
bool is_valid,
const GURL& endpoint,
const std::optional<base::Time>& expiration_time,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth) { … }
void PushMessagingServiceImpl::FirePushSubscriptionChange(
const PushMessagingAppIdentifier& app_identifier,
base::OnceClosure completed_closure,
blink::mojom::PushSubscriptionPtr new_subscription,
blink::mojom::PushSubscriptionPtr old_subscription) { … }
void PushMessagingServiceImpl::FirePushSubscriptionChangeCallback(
const PushMessagingAppIdentifier& app_identifier,
blink::mojom::PushEventStatus status) { … }
void PushMessagingServiceImpl::DidGetSenderIdUnexpectedUnsubscribe(
const PushMessagingAppIdentifier& app_identifier,
blink::mojom::PushUnregistrationReason reason,
UnregisterCallback callback,
const std::string& sender_id) { … }
void PushMessagingServiceImpl::SetContentSettingChangedCallbackForTesting(
base::RepeatingClosure callback) { … }
void PushMessagingServiceImpl::Shutdown() { … }
void PushMessagingServiceImpl::OnAppTerminating() { … }
void PushMessagingServiceImpl::OnSubscriptionInvalidation(
const std::string& app_id) { … }
void PushMessagingServiceImpl::GetOldSubscription(
PushMessagingAppIdentifier old_app_identifier,
const std::string& sender_id) { … }
void PushMessagingServiceImpl::StartRefresh(
PushMessagingAppIdentifier old_app_identifier,
const std::string& sender_id,
blink::mojom::PushSubscriptionPtr old_subscription) { … }
void PushMessagingServiceImpl::UpdateSubscription(
PushMessagingAppIdentifier app_identifier,
blink::mojom::PushSubscriptionOptionsPtr options,
RegisterCallback callback) { … }
void PushMessagingServiceImpl::DidUpdateSubscription(
const std::string& new_app_id,
const std::string& old_app_id,
blink::mojom::PushSubscriptionPtr old_subscription,
const std::string& sender_id,
const std::string& registration_id,
const GURL& endpoint,
const std::optional<base::Time>& expiration_time,
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
blink::mojom::PushRegistrationStatus status) { … }
void PushMessagingServiceImpl::OnOldSubscriptionExpired(
const std::string& app_id,
const std::string& sender_id) { … }
void PushMessagingServiceImpl::OnRefreshFinished(
const PushMessagingAppIdentifier& app_identifier) { … }
void PushMessagingServiceImpl::SetInvalidationCallbackForTesting(
base::OnceClosure callback) { … }
void PushMessagingServiceImpl::SetRemoveExpiredSubscriptionsCallbackForTesting(
base::OnceClosure closure) { … }
bool PushMessagingServiceImpl::IsPermissionSet(const GURL& origin,
bool user_visible) { … }
void PushMessagingServiceImpl::GetEncryptionInfoForAppId(
const std::string& app_id,
const std::string& sender_id,
gcm::GCMEncryptionProvider::EncryptionInfoCallback callback) { … }
gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { … }
instance_id::InstanceIDDriver* PushMessagingServiceImpl::GetInstanceIDDriver()
const { … }
content::DevToolsBackgroundServicesContext*
PushMessagingServiceImpl::GetDevToolsContext(const GURL& origin) const { … }