#include "chrome/browser/dips/dips_bounce_detector.h"
#include <iterator>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <vector>
#include "base/base64.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gmock_expected_support.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/test_future.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/dips/dips_redirect_info.h"
#include "chrome/browser/dips/dips_service.h"
#include "chrome/browser/dips/dips_storage.h"
#include "chrome/browser/dips/dips_test_utils.h"
#include "chrome/browser/dips/dips_utils.h"
#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
#include "chrome/browser/tpcd/heuristics/opener_heuristic_tab_helper.h"
#include "chrome/browser/tpcd/heuristics/redirect_heuristic_tab_helper.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/platform_browser_test.h"
#include "components/content_settings/common/content_settings_manager.mojom.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations.h"
#include "components/privacy_sandbox/tracking_protection_prefs.h"
#include "components/subresource_filter/core/common/test_ruleset_utils.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/back_forward_cache.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cookie_access_details.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/interest_group_manager.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_devtools_protocol_client.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/features.h"
#include "services/network/test/trust_token_request_handler.h"
#include "services/network/test/trust_token_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h"
#include "third_party/metrics_proto/ukm/source.pb.h"
#include "url/gurl.h"
#include "url/origin.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ssl/cert_verifier_browser_test.h"
#include "chrome/browser/ui/browser.h"
#include "content/public/browser/scoped_authenticator_environment_for_testing.h"
#include "device/fido/virtual_fido_device_factory.h"
#endif
Bucket;
CookieAccessDetails;
NavigationHandle;
WebContents;
Contains;
ElementsAre;
Eq;
Gt;
IsEmpty;
Pair;
DIPS_Redirect;
AttributionData;
namespace {
StorageTypeAccessed;
std::string FormatURL(const GURL& url) { … }
void AppendRedirect(std::vector<std::string>* redirects,
const DIPSRedirectInfo& redirect,
const DIPSRedirectChainInfo& chain,
size_t redirect_index) { … }
void AppendRedirects(std::vector<std::string>* vec,
std::vector<DIPSRedirectInfoPtr> redirects,
DIPSRedirectChainInfoPtr chain) { … }
void AppendSitesInReport(std::vector<std::string>* reports,
const std::set<std::string>& sites) { … }
std::vector<url::Origin> GetOrigins(const AttributionData& data) { … }
}
class WCOCallbackLogger
: public content::WebContentsObserver,
public content::WebContentsUserData<WCOCallbackLogger>,
public content::SharedWorkerService::Observer,
public content::DedicatedWorkerService::Observer { … };
WCOCallbackLogger::WCOCallbackLogger(content::WebContents* web_contents)
: … { … }
void WCOCallbackLogger::DidStartNavigation(
NavigationHandle* navigation_handle) { … }
void WCOCallbackLogger::OnCookiesAccessed(
content::RenderFrameHost* render_frame_host,
const content::CookieAccessDetails& details) { … }
void WCOCallbackLogger::OnCookiesAccessed(
NavigationHandle* navigation_handle,
const content::CookieAccessDetails& details) { … }
void WCOCallbackLogger::OnServiceWorkerAccessed(
content::RenderFrameHost* render_frame_host,
const GURL& scope,
content::AllowServiceWorkerResult allowed) { … }
void WCOCallbackLogger::OnServiceWorkerAccessed(
content::NavigationHandle* navigation_handle,
const GURL& scope,
content::AllowServiceWorkerResult allowed) { … }
void WCOCallbackLogger::OnClientAdded(
const blink::SharedWorkerToken& token,
content::GlobalRenderFrameHostId render_frame_host_id) { … }
void WCOCallbackLogger::OnWorkerCreated(
const blink::DedicatedWorkerToken& worker_token,
int worker_process_id,
const url::Origin& security_origin,
content::DedicatedWorkerCreator creator) { … }
void WCOCallbackLogger::DidFinishNavigation(
NavigationHandle* navigation_handle) { … }
void WCOCallbackLogger::WebAuthnAssertionRequestSucceeded(
content::RenderFrameHost* render_frame_host) { … }
void WCOCallbackLogger::NotifyStorageAccessed(
content::RenderFrameHost* render_frame_host,
StorageTypeAccessed storage_type,
bool blocked) { … }
WEB_CONTENTS_USER_DATA_KEY_IMPL(WCOCallbackLogger);
class DIPSBounceDetectorBrowserTest
: public subresource_filter::SubresourceFilterBrowserTest { … };
IN_PROC_BROWSER_TEST_F(
DIPSBounceDetectorBrowserTest,
DISABLED_AttributeSameSiteIframesCookieClientAccessTo1P) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_AttributeSameSiteIframesCookieServerAccessTo1P …
#else
#define MAYBE_AttributeSameSiteIframesCookieServerAccessTo1P …
#endif
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
MAYBE_AttributeSameSiteIframesCookieServerAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
Attribute3PIframesCHIPSClientAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DISABLED_Attribute3PIframesCHIPSServerAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(
DIPSBounceDetectorBrowserTest,
DISABLED_AttributeSameSiteNestedIframesCookieClientAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(
DIPSBounceDetectorBrowserTest,
DISABLED_AttributeSameSiteNestedIframesCookieServerAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
Attribute3PNestedIframesCHIPSClientAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
Attribute3PNestedIframesCHIPSServerAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
Attribute3PSubResourceCHIPSClientAccessTo1P) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DiscardFencedFrameCookieClientAccess) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DiscardFencedFrameCookieServerAccess) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_DiscardPrerenderedPageCookieClientAccess …
#else
#define MAYBE_DiscardPrerenderedPageCookieClientAccess …
#endif
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
MAYBE_DiscardPrerenderedPageCookieClientAccess) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DISABLED_DiscardPrerenderedPageCookieServerAccess) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DetectStatefulBounce_ClientRedirect_SiteDataAccess) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
AllCookieCallbacksBeforeNavigationFinished) { … }
std::unique_ptr<net::test_server::HttpResponse>
HandleCrossSiteSameSiteNoneCookieRedirect(
net::EmbeddedTestServer* server,
const net::test_server::HttpRequest& request) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
IgnoreServerRedirectsInIframes) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
ReportRedirectorsInChain_OmitSitesWithInteraction) { … }
IN_PROC_BROWSER_TEST_F(
DIPSBounceDetectorBrowserTest,
DetectStatefulRedirect_Client_IgnoreThirdPartySubresource) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DetectStatefulRedirect_Client_FirstPartySubresource) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DetectStatefulRedirect_ServerClientClientServer) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DetectStatefulRedirect_ClosingTabEndsChain) { … }
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
#define MAYBE_OpenServerRedirectURLInNewTab …
#else
#define MAYBE_OpenServerRedirectURLInNewTab …
#endif
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
MAYBE_OpenServerRedirectURLInNewTab) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
OpenClientRedirectURLInNewTab) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
OpenRedirectURLInNewTab_OpaqueOriginInitiator) { … }
class RedirectHeuristicBrowserTest : public PlatformBrowserTest { … };
IN_PROC_BROWSER_TEST_F(RedirectHeuristicBrowserTest,
RecordsRedirectHeuristicCookieAccessEvent) { … }
IN_PROC_BROWSER_TEST_F(RedirectHeuristicBrowserTest,
DISABLED_RedirectHeuristicCookieAccessEvent_AllMetrics) { … }
struct RedirectHeuristicFlags { … };
#if !BUILDFLAG(IS_ANDROID)
class RedirectHeuristicGrantTest
: public RedirectHeuristicBrowserTest,
public testing::WithParamInterface<RedirectHeuristicFlags> { … };
IN_PROC_BROWSER_TEST_P(RedirectHeuristicGrantTest,
CreatesRedirectHeuristicGrantsWithSatisfyingURL) { … }
IN_PROC_BROWSER_TEST_P(
RedirectHeuristicGrantTest,
CreatesRedirectHeuristicGrantsWithPartiallySatisfyingURL) { … }
const RedirectHeuristicFlags kRedirectHeuristicTestCases[] = …;
INSTANTIATE_TEST_SUITE_P(…);
#endif
class DIPSBounceTrackingDevToolsIssueTest
: public content::TestDevToolsProtocolClient,
public DIPSBounceDetectorBrowserTest { … };
IN_PROC_BROWSER_TEST_F(DIPSBounceTrackingDevToolsIssueTest,
BounceTrackingDevToolsIssue) { … }
class DIPSSiteDataAccessDetectorTest
: public DIPSBounceDetectorBrowserTest,
public testing::WithParamInterface<StorageTypeAccessed> { … };
IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest,
DetectSiteDataAccess_Storages) { … }
IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest,
AttributeSameSiteIframesSiteDataAccessTo1P) { … }
IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest,
AttributeSameSiteNestedIframesSiteDataAccessTo1P) { … }
IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest,
DiscardFencedFrameCookieClientAccess) { … }
IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest,
DiscardPrerenderedPageCookieClientAccess) { … }
INSTANTIATE_TEST_SUITE_P(…);
#if !BUILDFLAG(IS_ANDROID)
class DIPSWebAuthnBrowserTest : public CertVerifierBrowserTest { … };
IN_PROC_BROWSER_TEST_F(DIPSWebAuthnBrowserTest,
WebAuthnAssertion_ConfirmWCOCallback) { … }
IN_PROC_BROWSER_TEST_F(
DIPSWebAuthnBrowserTest,
ReportRedirectorsInChain_OmitSitesWithWebAuthnAssertions) { … }
#endif
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
ServiceWorkerAccess_Storages) { … }
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_SharedWorkerAccess_Storages …
#else
#define MAYBE_SharedWorkerAccess_Storages …
#endif
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
MAYBE_SharedWorkerAccess_Storages) { … }
IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
DedicatedWorkerAccess_Storages) { … }
class DIPSBounceTriggerBrowserTest : public DIPSBounceDetectorBrowserTest { … };
IN_PROC_BROWSER_TEST_F(DIPSBounceTriggerBrowserTest, NoContent) { … }
class DIPSThrottlingBrowserTest : public DIPSBounceDetectorBrowserTest { … };
IN_PROC_BROWSER_TEST_F(DIPSThrottlingBrowserTest,
InteractionRecording_Throttled) { … }
IN_PROC_BROWSER_TEST_F(DIPSThrottlingBrowserTest,
InteractionRecording_NotThrottled_AfterRefresh) { … }
IN_PROC_BROWSER_TEST_F(DIPSThrottlingBrowserTest,
DISABLED_StorageRecording_Throttled) { … }
IN_PROC_BROWSER_TEST_F(DIPSThrottlingBrowserTest,
DISABLED_StorageRecording_NotThrottled_AfterRefresh) { … }
class AllSitesFollowingFirstPartyTest : public PlatformBrowserTest { … };
IN_PROC_BROWSER_TEST_F(AllSitesFollowingFirstPartyTest,
SiteFollowingFirstPartyIncluded) { … }
IN_PROC_BROWSER_TEST_F(AllSitesFollowingFirstPartyTest,
SiteNotFollowingFirstPartyNotIncluded) { … }
IN_PROC_BROWSER_TEST_F(AllSitesFollowingFirstPartyTest, MultipleSitesIncluded) { … }
IN_PROC_BROWSER_TEST_F(AllSitesFollowingFirstPartyTest,
NoFirstParty_NothingIncluded) { … }
IN_PROC_BROWSER_TEST_F(AllSitesFollowingFirstPartyTest,
NothingAfterFirstParty_NothingIncluded) { … }
class DIPSPrivacySandboxApiInteractionTest : public PlatformBrowserTest { … };
IN_PROC_BROWSER_TEST_F(DIPSPrivacySandboxApiInteractionTest,
DontTriggerDeletionOnProtectedAudienceApiStorageAccess) { … }
IN_PROC_BROWSER_TEST_F(
DIPSPrivacySandboxApiInteractionTest,
DontTriggerDeletionOnAttributionReportingApiStorageAccess) { … }
IN_PROC_BROWSER_TEST_F(
DIPSPrivacySandboxApiInteractionTest,
DontTriggerDeletionOnPrivateStateTokensApiStorageAccess) { … }
IN_PROC_BROWSER_TEST_F(DIPSPrivacySandboxApiInteractionTest,
DontTriggerDeletionOnTopicsApiStorageAccess) { … }
class DIPSPrivacySandboxDataPreservationTest
: public DIPSPrivacySandboxApiInteractionTest,
public testing::WithParamInterface<bool> { … };
IN_PROC_BROWSER_TEST_P(DIPSPrivacySandboxDataPreservationTest,
DontClearAttributionReportingApiData) { … }
INSTANTIATE_TEST_SUITE_P(…);
namespace {
class SiteStorage { … };
class CookieStorage : public SiteStorage { … };
class LocalStorage : public SiteStorage { … };
void PrintTo(const SiteStorage* storage, std::ostream* os) { … }
static constexpr CookieStorage kCookieStorage;
static constexpr LocalStorage kLocalStorage;
}
class DIPSDataDeletionBrowserTest
: public DIPSBounceDetectorBrowserTest,
public testing::WithParamInterface<const SiteStorage*> { … };
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest, DeleteDomain) { … }
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest, DontDeleteOtherDomains) { … }
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest,
DontDeleteDomainWhenPartitioned) { … }
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest, DeleteSubdomains) { … }
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest, DeleteEmbedded3Ps) { … }
IN_PROC_BROWSER_TEST_P(DIPSDataDeletionBrowserTest,
DeleteEmbedded3Ps_Subdomain) { … }
INSTANTIATE_TEST_SUITE_P(…);
class DIPSBounceDetectorBFCacheTest : public DIPSBounceDetectorBrowserTest,
public testing::WithParamInterface<bool> { … };
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest, LateCookieAccessTest) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest, QuickEndChainTest) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest, CookieAccessReported) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest, LateInteractionTest) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest, IsOrWasInPrimaryPage) { … }
class PrerenderingObserver : public content::WebContentsObserver { … };
void PrerenderingObserver::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest,
PrerenderedPagesAreNotPrimary) { … }
IN_PROC_BROWSER_TEST_P(DIPSBounceDetectorBFCacheTest,
PrerenderedPagesCanBecomePrimary) { … }
INSTANTIATE_TEST_SUITE_P(…);