chromium/chrome/browser/push_messaging/push_messaging_browsertest.cc

// 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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <string>

#include "base/barrier_closure.h"
#include "base/base64url.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
#include "chrome/browser/content_settings/cookie_settings_factory.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/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/notification_handler.h"
#include "chrome/browser/permissions/crowd_deny_fake_safe_browsing_database_manager.h"
#include "chrome/browser/permissions/crowd_deny_preload_data.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_service_impl.h"
#include "chrome/browser/push_messaging/push_messaging_utils.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/browsing_data/content/browsing_data_helper.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/gcm_driver/common/gcm_message.h"
#include "components/gcm_driver/fake_gcm_profile_service.h"
#include "components/gcm_driver/gcm_client.h"
#include "components/gcm_driver/instance_id/fake_gcm_driver_for_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/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/permissions/permission_request_manager.h"
#include "components/site_engagement/content/site_engagement_score.h"
#include "components/site_engagement/content/site_engagement_service.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_utils.h"
#include "net/base/features.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
#include "ui/base/window_open_disposition.h"
#include "ui/message_center/public/cpp/notification.h"

#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
#include "chrome/browser/background/background_mode_manager.h"
#endif

namespace {

const char kManifestSenderId[] =;
const int32_t kApplicationServerKeyLength =;

enum class PushSubscriptionKeyFormat {};

// NIST P-256 public key made available to tests. Must be an uncompressed
// point in accordance with SEC1 2.3.3.
const uint8_t kApplicationServerKey[kApplicationServerKeyLength] =;

// URL-safe base64 encoded version of the |kApplicationServerKey|.
const char kEncodedApplicationServerKey[] =;

// From chrome/browser/push_messaging/push_messaging_manager.cc
const char* kIncognitoWarningPattern =;

std::string GetTestApplicationServerKey(bool base64_url_encoded = false) {}

void LegacyRegisterCallback(base::OnceClosure done_callback,
                            std::string* out_registration_id,
                            gcm::GCMClient::Result* out_result,
                            const std::string& registration_id,
                            gcm::GCMClient::Result result) {}

void DidRegister(base::OnceClosure done_callback,
                 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 InstanceIDResultCallback(base::OnceClosure done_callback,
                              instance_id::InstanceID::Result* out_result,
                              instance_id::InstanceID::Result result) {}

}  // namespace

class PushMessagingBrowserTestBase : public InProcessBrowserTest {};

void PushMessagingBrowserTestBase::RequestAndAcceptPermission() {}

void PushMessagingBrowserTestBase::RequestAndDenyPermission() {}

void PushMessagingBrowserTestBase::SubscribeSuccessfully(
    PushSubscriptionKeyFormat key_format,
    std::string* out_token) {}

void PushMessagingBrowserTestBase::SetupOrphanedPushSubscription(
    std::string* out_app_id) {}

void PushMessagingBrowserTestBase::LegacySubscribeSuccessfully(
    std::string* out_subscription_id) {}

void PushMessagingBrowserTestBase::EndpointToToken(const std::string& endpoint,
                                                   bool standard_protocol,
                                                   std::string* out_token) {}

PushMessagingAppIdentifier
PushMessagingBrowserTestBase::GetAppIdentifierForServiceWorkerRegistration(
    int64_t service_worker_registration_id) {}

void PushMessagingBrowserTestBase::DeleteInstanceIDAsIfGCMStoreReset(
    const std::string& app_id) {}

void PushMessagingBrowserTestBase::SendMessageAndWaitUntilHandled(
    const PushMessagingAppIdentifier& app_identifier,
    const gcm::IncomingMessage& message) {}

class PushMessagingBrowserTest : public PushMessagingBrowserTestBase {};

// This class is used to execute PushMessagingBrowserTest tests with
// third-party storage partitioning both enabled/disabled.
class PushMessagingPartitionedBrowserTest
    : public PushMessagingBrowserTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeWithoutKeySuccessNotificationsGranted) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeSuccessNotificationsGranted) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeSuccessNotificationsGrantedWithBase64URLKey) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeSuccessNotificationsPrompt) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeFailureNotificationsBlocked) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribeFailureNoManifest) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribeFailureNoSenderId) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       RegisterFailureEmptyPushSubscriptionOptions) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribeWithInvalidation) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribeWorker) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       SubscribeWorkerWithBase64URLEncodedString) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       ResubscribeWithoutKeyAfterSubscribingWithKeyInManifest) {}

IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTest,
    ResubscribeWithoutKeyAfterSubscribingFromDocumentWithP256Key) {}

IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTest,
    ResubscribeWithoutKeyAfterSubscribingFromWorkerWithP256Key) {}

IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTest,
    ResubscribeWithoutKeyAfterSubscribingFromDocumentWithNumber) {}

IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTest,
    ResubscribeWithoutKeyAfterSubscribingFromWorkerWithNumber) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, ResubscribeWithMismatchedKey) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribePersisted) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, AppHandlerOnlyIfSubscribed) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventSuccess) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventOnShutdown) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventWithoutPayload) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, LegacyPushEvent) {}

// Some users may have gotten into a state in the past where they still have
// a subscription even though the service worker was unregistered.
// Emulate this and test a push message triggers unsubscription.
IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventNoServiceWorker) {}

// Tests receiving messages for a subscription that no longer exists.
IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, NoSubscription) {}

// Tests receiving messages for an origin that does not have permission, but
// somehow still has a subscription (as happened in https://crbug.com/633310).
IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventWithoutPermission) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       PushEventEnforcesUserVisibleNotification) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       PushEventAllowSilentPushCommandLineFlag) {}

class PushMessagingBrowserTestWithAbusiveOriginPermissionRevocation
    : public PushMessagingBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTestWithAbusiveOriginPermissionRevocation,
    PushEventPermissionRevoked) {}

// That test verifies that an origin is not revoked because it is not on
// SafeBrowsing blocking list.
IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTestWithAbusiveOriginPermissionRevocation,
    OriginIsNotOnSafeBrowsingBlockingList) {}

class PushMessagingBrowserTestWithNotificationTriggersEnabled
    : public PushMessagingBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTestWithNotificationTriggersEnabled,
                       PushEventIgnoresScheduledNotificationsForEnforcement) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       PushEventEnforcesUserVisibleNotificationAfterQueue) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       PushEventNotificationWithoutEventWaitUntil) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysPrompt) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysGranted) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysDenied) {}

IN_PROC_BROWSER_TEST_P(PushMessagingPartitionedBrowserTest, CrossOriginFrame) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, UnsubscribeSuccess) {}

// Push subscriptions used to be non-InstanceID GCM registrations. Still need
// to be able to unsubscribe these, even though new ones are no longer created.
// Flaky on some Win and Linux buildbots.  See crbug.com/835382.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_LegacyUnsubscribeSuccess
#else
#define MAYBE_LegacyUnsubscribeSuccess
#endif
IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       MAYBE_LegacyUnsubscribeSuccess) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, UnsubscribeOffline) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       UnregisteringServiceWorkerUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       ServiceWorkerDatabaseDeletionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       InvalidGetSubscriptionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       GlobalResetPushPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       LocalResetPushPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       DenyPushPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       GlobalResetNotificationsPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       LocalResetNotificationsPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       DenyNotificationsPermissionUnsubscribes) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       GrantAlreadyGrantedPermissionDoesNotUnsubscribe) {}

// This test is testing some non-trivial content settings rules and make sure
// that they are respected with regards to automatic unsubscription. In other
// words, it checks that the push service does not end up unsubscribing origins
// that have push permission with some non-common rules.
IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest,
                       AutomaticUnsubscriptionFollowsContentSettingRules) {}

// Checks automatically unsubscribing due to a revoked permission after
// previously clearing site data, under legacy conditions (ie. when
// unregistering a worker did not unsubscribe from push.)
IN_PROC_BROWSER_TEST_F(
    PushMessagingBrowserTest,
    ResetPushPermissionAfterClearingSiteDataUnderLegacyConditions) {}

IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, EncryptionKeyUniqueness) {}

class PushMessagingIncognitoBrowserTest : public PushMessagingBrowserTestBase {};

// Regression test for https://crbug.com/476474
IN_PROC_BROWSER_TEST_F(PushMessagingIncognitoBrowserTest,
                       IncognitoGetSubscriptionDoesNotHang) {}

IN_PROC_BROWSER_TEST_F(PushMessagingIncognitoBrowserTest, WarningToCorrectRFH) {}

// TODO(crbug.com/40204670): This test hits the issue. Re-enable after it
// is fixed.
IN_PROC_BROWSER_TEST_F(PushMessagingIncognitoBrowserTest,
                       DISABLED_WarningToCorrectRFH_Prerender) {}

class PushMessagingDisallowSenderIdsBrowserTest
    : public PushMessagingBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(PushMessagingDisallowSenderIdsBrowserTest,
                       SubscriptionWithSenderIdFails) {}

class PushSubscriptionWithExpirationTimeTest
    : public PushMessagingBrowserTestBase {};

bool PushSubscriptionWithExpirationTimeTest::IsExpirationTimeValid(
    const std::string& expiration_time) {}

IN_PROC_BROWSER_TEST_F(PushSubscriptionWithExpirationTimeTest,
                       SubscribeGetSubscriptionWithExpirationTime) {}

IN_PROC_BROWSER_TEST_F(PushSubscriptionWithExpirationTimeTest,
                       GetSubscriptionWithExpirationTime) {}

class PushSubscriptionWithoutExpirationTimeTest
    : public PushMessagingBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(PushSubscriptionWithoutExpirationTimeTest,
                       SubscribeDocumentExpirationTimeNull) {}

class PushSubscriptionChangeEventTest : public PushMessagingBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(PushSubscriptionChangeEventTest,
                       PushSubscriptionChangeEventSuccess) {}

IN_PROC_BROWSER_TEST_F(PushSubscriptionChangeEventTest,
                       FiredAfterPermissionRevoked) {}

IN_PROC_BROWSER_TEST_F(PushSubscriptionChangeEventTest, OnInvalidation) {}