#include "chrome/browser/dips/dips_bounce_detector.h"
#include <cmath>
#include <cstddef>
#include <ctime>
#include <memory>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/overloaded.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/types/optional_ref.h"
#include "chrome/browser/dips/cookie_access_filter.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_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tpcd/experiment/tpcd_experiment_features.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cookie_access_details.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/page.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "net/cookies/canonical_cookie.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
NavigationHandle;
ServerBounceDetectionState::ServerBounceDetectionState() = default;
ServerBounceDetectionState::~ServerBounceDetectionState() = default;
ServerBounceDetectionState::ServerBounceDetectionState(
NavigationHandle& navigation_handle) { … }
NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(ServerBounceDetectionState);
ClientBounceDetectionState::ClientBounceDetectionState(
const ClientBounceDetectionState& other) = default;
ClientBounceDetectionState::~ClientBounceDetectionState() = default;
ClientBounceDetectionState::ClientBounceDetectionState(
GURL url,
std::string site,
base::TimeTicks load_time) { … }
namespace …
void DIPSWebContentsObserver::MaybeCreateForWebContents(
content::WebContents* web_contents) { … }
DIPSWebContentsObserver::DIPSWebContentsObserver(
content::WebContents* web_contents,
DIPSServiceImpl* dips_service)
: … { … }
DIPSWebContentsObserver::~DIPSWebContentsObserver() = default;
RedirectChainDetector::RedirectChainDetector(content::WebContents* web_contents)
: … { … }
RedirectChainDetector::~RedirectChainDetector() = default;
DIPSBounceDetector::DIPSBounceDetector(DIPSBounceDetectorDelegate* delegate,
const base::TickClock* tick_clock,
const base::Clock* clock)
: … { … }
DIPSBounceDetector::~DIPSBounceDetector() = default;
DIPSBounceDetectorDelegate::~DIPSBounceDetectorDelegate() = default;
DIPSNavigationHandle::~DIPSNavigationHandle() = default;
ukm::SourceId DIPSNavigationHandle::GetRedirectSourceId(int index) const { … }
DIPSRedirectContext::DIPSRedirectContext(DIPSRedirectChainHandler handler,
DIPSIssueHandler issue_handler,
const UrlAndSourceId& initial_url,
size_t redirect_prefix_count)
: … { … }
DIPSRedirectContext::~DIPSRedirectContext() = default;
void DIPSRedirectContext::AppendClientRedirect(
DIPSRedirectInfoPtr client_redirect) { … }
void DIPSRedirectContext::AppendServerRedirects(
std::vector<DIPSRedirectInfoPtr> server_redirects) { … }
void DIPSRedirectContext::TrimRedirectsFromFront() { … }
void DIPSRedirectContext::ReportIssue(const GURL& final_url) { … }
std::optional<std::pair<size_t, DIPSRedirectInfo*>>
DIPSRedirectContext::GetRedirectInfoFromChain(const std::string& site) const { … }
bool DIPSRedirectContext::SiteHadUserActivation(const std::string& site) const { … }
std::set<std::string> DIPSRedirectContext::AllSitesWithUserActivation() const { … }
std::map<std::string, std::pair<GURL, bool>>
DIPSRedirectContext::GetRedirectHeuristicURLs(
const GURL& first_party_url,
std::optional<std::set<std::string>> allowed_sites) const { … }
void DIPSRedirectContext::HandleUncommitted(
DIPSNavigationStart navigation_start,
std::vector<DIPSRedirectInfoPtr> server_redirects) { … }
void DIPSRedirectContext::AppendCommitted(
DIPSNavigationStart navigation_start,
std::vector<DIPSRedirectInfoPtr> server_redirects,
const UrlAndSourceId& final_url,
bool current_page_has_sticky_activation) { … }
void DIPSRedirectContext::TrimAndHandleRedirects(size_t trim_count) { … }
void DIPSRedirectContext::EndChain(UrlAndSourceId final_url,
bool current_page_has_sticky_activation) { … }
namespace {
bool AddLateCookieAccess(const GURL& url,
CookieOperation op,
std::vector<DIPSRedirectInfoPtr>& redirects) { … }
}
bool DIPSRedirectContext::AddLateCookieAccess(const GURL& url,
CookieOperation op) { … }
void DIPSWebContentsObserver::EmitDIPSIssue(
const std::set<std::string>& sites) { … }
void RedirectChainDetector::ReportRedirectors(std::set<std::string> sites) { … }
void DIPSWebContentsObserver::ReportRedirectors(
const std::set<std::string>& sites) { … }
void DIPSWebContentsObserver::RecordEvent(DIPSRecordedEvent event,
const GURL& url,
const base::Time& time) { … }
UrlAndSourceId RedirectChainDetector::GetLastCommittedURL() const { … }
void RedirectChainDetector::HandleRedirectChain(
std::vector<DIPSRedirectInfoPtr> redirects,
DIPSRedirectChainInfoPtr chain) { … }
void RedirectChainDetector::NotifyOnRedirectChainEnded(
std::vector<DIPSRedirectInfoPtr> redirects,
DIPSRedirectChainInfoPtr chain) { … }
void DIPSWebContentsObserver::OnRedirectChainEnded(
const std::vector<DIPSRedirectInfoPtr>& redirects,
const DIPSRedirectChainInfo& chain) { … }
void DIPSWebContentsObserver::IncrementPageSpecificBounceCount(
const GURL& final_url) { … }
class DIPSNavigationHandleImpl : public DIPSNavigationHandle { … };
void RedirectChainDetector::DidStartNavigation(
NavigationHandle* navigation_handle) { … }
void DIPSBounceDetector::DidStartNavigation(
DIPSNavigationHandle* navigation_handle) { … }
void RedirectChainDetector::NotifyStorageAccessed(
content::RenderFrameHost* render_frame_host,
blink::mojom::StorageTypeAccessed storage_type,
bool blocked) { … }
void RedirectChainDetector::PrimaryPageChanged(content::Page& page) { … }
namespace dips {
bool IsOrWasInPrimaryPage(content::RenderFrameHost* render_frame_host) { … }
}
void RedirectChainDetector::OnCookiesAccessed(
content::RenderFrameHost* render_frame_host,
const content::CookieAccessDetails& details) { … }
void DIPSWebContentsObserver::OnSiteStorageAccessed(const GURL& first_party_url,
CookieOperation op,
bool http_cookie) { … }
void RedirectChainDetector::OnCookiesAccessed(
NavigationHandle* navigation_handle,
const content::CookieAccessDetails& details) { … }
void DIPSBounceDetector::OnClientSiteDataAccessed(const GURL& url,
CookieOperation op) { … }
void DIPSBounceDetector::OnServerCookiesAccessed(
DIPSNavigationHandle* navigation_handle,
const GURL& url,
CookieOperation op) { … }
void RedirectChainDetector::OnSiteStorageAccessed(const GURL& first_party_url,
CookieOperation op,
bool http_cookie) { … }
void DIPSWebContentsObserver::OnServiceWorkerAccessed(
content::RenderFrameHost* render_frame_host,
const GURL& scope,
content::AllowServiceWorkerResult allowed) { … }
void DIPSWebContentsObserver::OnServiceWorkerAccessed(
content::NavigationHandle* navigation_handle,
const GURL& scope,
content::AllowServiceWorkerResult allowed) { … }
void DIPSWebContentsObserver::OnClientAdded(
const blink::SharedWorkerToken& token,
content::GlobalRenderFrameHostId render_frame_host_id) { … }
void DIPSWebContentsObserver::OnWorkerCreated(
const blink::DedicatedWorkerToken& worker_token,
int worker_process_id,
const url::Origin& security_origin,
content::DedicatedWorkerCreator creator) { … }
void DIPSWebContentsObserver::PrimaryPageChanged(content::Page& page) { … }
void RedirectChainDetector::DidFinishNavigation(
NavigationHandle* navigation_handle) { … }
void DIPSBounceDetector::DidFinishNavigation(
DIPSNavigationHandle* navigation_handle) { … }
void RedirectChainDetector::FrameReceivedUserActivation(
content::RenderFrameHost* render_frame_host) { … }
void DIPSBounceDetector::OnUserActivation() { … }
void DIPSWebContentsObserver::FrameReceivedUserActivation(
content::RenderFrameHost* render_frame_host) { … }
void DIPSBounceDetector::WebAuthnAssertionRequestSucceeded() { … }
void RedirectChainDetector::WebAuthnAssertionRequestSucceeded(
content::RenderFrameHost* render_frame_host) { … }
void DIPSWebContentsObserver::WebAuthnAssertionRequestSucceeded(
content::RenderFrameHost* render_frame_host) { … }
void DIPSWebContentsObserver::WebContentsDestroyed() { … }
void RedirectChainDetector::WebContentsDestroyed() { … }
void DIPSBounceDetector::BeforeDestruction() { … }
void DIPSBounceDetector::OnClientBounceDetectionTimeout() { … }
WEB_CONTENTS_USER_DATA_KEY_IMPL(RedirectChainDetector);
WEB_CONTENTS_USER_DATA_KEY_IMPL(DIPSWebContentsObserver);
namespace dips {
ukm::SourceId GetInitialRedirectSourceId(
content::NavigationHandle* navigation_handle) { … }
}
void RedirectChainDetector::AddObserver(Observer* observer) { … }
void RedirectChainDetector::RemoveObserver(const Observer* observer) { … }
DelayedChainHandler::DelayedChainHandler(DIPSRedirectChainHandler handler)
: … { … }
DelayedChainHandler::~DelayedChainHandler() = default;
void DelayedChainHandler::HandleRedirectChain(
std::vector<DIPSRedirectInfoPtr> redirects,
DIPSRedirectChainInfoPtr chain) { … }
bool DelayedChainHandler::AddLateCookieAccess(const GURL& url,
CookieOperation op) { … }
void DelayedChainHandler::HandlePreviousChainNowImpl(bool timer_fired) { … }