#include "components/page_load_metrics/browser/page_load_tracker.h"
#include <algorithm>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include "base/check_op.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "components/page_load_metrics/browser/features.h"
#include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
#include "components/page_load_metrics/browser/page_load_metrics_forward_observer.h"
#include "components/page_load_metrics/browser/page_load_metrics_memory_tracker.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
#include "components/page_load_metrics/browser/page_load_metrics_util.h"
#include "components/page_load_metrics/common/page_load_timing.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_discard_reason.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "page_load_metrics_observer_delegate.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/mojom/input/input_event.mojom-shared.h"
namespace page_load_metrics {
namespace internal {
const char kErrorEvents[] = …;
const char kPageLoadPrerender2Event[] = …;
const char kPageLoadPrerender2VisibilityAtActivation[] = …;
const char kPageLoadTrackerPageType[] = …;
}
void RecordInternalError(InternalErrorLoadEvent event) { … }
void RecordPageType(internal::PageLoadTrackerPageType type) { … }
PageEndReason EndReasonForPageTransition(ui::PageTransition transition) { … }
bool IsNavigationUserInitiated(content::NavigationHandle* handle) { … }
namespace {
void DispatchEventsAfterBackForwardCacheRestore(
PageLoadMetricsObserverInterface* observer,
const std::vector<mojo::StructPtr<mojom::BackForwardCacheTiming>>&
last_timings,
const std::vector<mojo::StructPtr<mojom::BackForwardCacheTiming>>&
new_timings) { … }
void DispatchObserverTimingCallbacks(PageLoadMetricsObserverInterface* observer,
const mojom::PageLoadTiming& last_timing,
const mojom::PageLoadTiming& new_timing) { … }
internal::PageLoadTrackerPageType CalculatePageType(
content::NavigationHandle* navigation_handle) { … }
bool CalculateIsOriginVisit(bool is_first_navigation,
ui::PageTransition transition) { … }
}
PageLoadTracker::PageLoadTracker(
bool in_foreground,
PageLoadMetricsEmbedderInterface* embedder_interface,
const GURL& currently_committed_url,
bool is_first_navigation_in_web_contents,
content::NavigationHandle* navigation_handle,
UserInitiatedInfo user_initiated_info,
ukm::SourceId source_id,
base::WeakPtr<PageLoadTracker> parent_tracker)
: … { … }
PageLoadTracker::~PageLoadTracker() { … }
void PageLoadTracker::PageHidden() { … }
void PageLoadTracker::PageShown() { … }
void PageLoadTracker::RenderFrameDeleted(content::RenderFrameHost* rfh) { … }
void PageLoadTracker::FrameTreeNodeDeleted(int frame_tree_node_id) { … }
void PageLoadTracker::WillProcessNavigationResponse(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::DidActivatePrerenderedPage(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::DidActivatePreviewedPage(
base::TimeTicks activation_time) { … }
void PageLoadTracker::DidCommitSameDocumentNavigation(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::DidInternalNavigationAbort(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::DidFinishSubFrameNavigation(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::FailedProvisionalLoad(
content::NavigationHandle* navigation_handle,
base::TimeTicks failed_load_time) { … }
void PageLoadTracker::DidUpdateNavigationHandleTiming(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { … }
void PageLoadTracker::FlushMetricsOnAppEnterBackground() { … }
void PageLoadTracker::OnLoadedResource(
const ExtraRequestCompleteInfo& extra_request_complete_info) { … }
void PageLoadTracker::FrameReceivedUserActivation(
content::RenderFrameHost* rfh) { … }
void PageLoadTracker::FrameDisplayStateChanged(
content::RenderFrameHost* render_frame_host,
bool is_display_none) { … }
void PageLoadTracker::FrameSizeChanged(
content::RenderFrameHost* render_frame_host,
const gfx::Size& frame_size) { … }
void PageLoadTracker::OnCookiesRead(
const GURL& url,
const GURL& first_party_url,
bool blocked_by_policy,
bool is_ad_tagged,
const net::CookieSettingOverrides& cookie_setting_overrides,
bool is_partitioned_access) { … }
void PageLoadTracker::OnCookieChange(
const GURL& url,
const GURL& first_party_url,
const net::CanonicalCookie& cookie,
bool blocked_by_policy,
bool is_ad_tagged,
const net::CookieSettingOverrides& cookie_setting_overrides,
bool is_partitioned_access) { … }
void PageLoadTracker::OnStorageAccessed(const GURL& url,
const GURL& first_party_url,
bool blocked_by_policy,
StorageType access_type) { … }
void PageLoadTracker::StopTracking() { … }
void PageLoadTracker::AddObserver(
std::unique_ptr<PageLoadMetricsObserverInterface> observer) { … }
base::WeakPtr<PageLoadMetricsObserverInterface> PageLoadTracker::FindObserver(
const char* name) { … }
void PageLoadTracker::ClampBrowserTimestampIfInterProcessTimeTickSkew(
base::TimeTicks* event_time) { … }
bool PageLoadTracker::HasMatchingNavigationRequestID(
const content::GlobalRequestID& request_id) const { … }
void PageLoadTracker::NotifyPageEnd(PageEndReason page_end_reason,
UserInitiatedInfo user_initiated_info,
base::TimeTicks timestamp,
bool is_certainly_browser_timestamp) { … }
void PageLoadTracker::UpdatePageEnd(PageEndReason page_end_reason,
UserInitiatedInfo user_initiated_info,
base::TimeTicks timestamp,
bool is_certainly_browser_timestamp) { … }
bool PageLoadTracker::IsLikelyProvisionalAbort(
base::TimeTicks abort_cause_time) const { … }
void PageLoadTracker::UpdatePageEndInternal(
PageEndReason page_end_reason,
UserInitiatedInfo user_initiated_info,
base::TimeTicks timestamp,
bool is_certainly_browser_timestamp) { … }
void PageLoadTracker::MediaStartedPlaying(
const content::WebContentsObserver::MediaPlayerInfo& video_type,
content::RenderFrameHost* render_frame_host) { … }
bool PageLoadTracker::IsPageMainFrame(content::RenderFrameHost* rfh) const { … }
void PageLoadTracker::OnTimingChanged() { … }
void PageLoadTracker::OnPageInputTimingChanged(uint64_t num_interactions) { … }
void PageLoadTracker::OnSubFrameTimingChanged(
content::RenderFrameHost* rfh,
const mojom::PageLoadTiming& timing) { … }
void PageLoadTracker::OnSubFrameInputTimingChanged(
content::RenderFrameHost* rfh,
const mojom::InputTiming& input_timing_delta) { … }
void PageLoadTracker::OnPageRenderDataChanged(
const mojom::FrameRenderDataUpdate& render_data,
bool is_main_frame) { … }
void PageLoadTracker::OnSubFrameRenderDataChanged(
content::RenderFrameHost* rfh,
const mojom::FrameRenderDataUpdate& render_data) { … }
void PageLoadTracker::OnMainFrameMetadataChanged() { … }
void PageLoadTracker::OnSubframeMetadataChanged(
content::RenderFrameHost* rfh,
const mojom::FrameMetadata& metadata) { … }
void PageLoadTracker::OnSoftNavigationChanged(
const mojom::SoftNavigationMetrics& new_soft_navigation_metrics) { … }
void PageLoadTracker::OnPrefetchLikely() { … }
void PageLoadTracker::UpdateFeaturesUsage(
content::RenderFrameHost* rfh,
const std::vector<blink::UseCounterFeature>& new_features) { … }
void PageLoadTracker::SetUpSharedMemoryForSmoothness(
base::ReadOnlySharedMemoryRegion shared_memory) { … }
void PageLoadTracker::UpdateResourceDataUse(
content::RenderFrameHost* rfh,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) { … }
void PageLoadTracker::UpdateFrameCpuTiming(content::RenderFrameHost* rfh,
const mojom::CpuTiming& timing) { … }
void PageLoadTracker::OnMainFrameIntersectionRectChanged(
content::RenderFrameHost* rfh,
const gfx::Rect& main_frame_intersection_rect) { … }
void PageLoadTracker::OnMainFrameViewportRectChanged(
const gfx::Rect& main_frame_viewport_rect) { … }
void PageLoadTracker::OnMainFrameImageAdRectsChanged(
const base::flat_map<int, gfx::Rect>& main_frame_image_ad_rects) { … }
content::WebContents* PageLoadTracker::GetWebContents() const { … }
base::TimeTicks PageLoadTracker::GetNavigationStart() const { … }
std::optional<base::TimeDelta>
PageLoadTracker::DurationSinceNavigationStartForTime(
const std::optional<base::TimeTicks>& time) const { … }
std::optional<base::TimeDelta> PageLoadTracker::GetTimeToFirstBackground()
const { … }
std::optional<base::TimeDelta> PageLoadTracker::GetTimeToFirstForeground()
const { … }
const PageLoadMetricsObserverDelegate::BackForwardCacheRestore&
PageLoadTracker::GetBackForwardCacheRestore(size_t index) const { … }
bool PageLoadTracker::StartedInForeground() const { … }
PageVisibility PageLoadTracker::GetVisibilityAtActivation() const { … }
bool PageLoadTracker::WasPrerenderedThenActivatedInForeground() const { … }
PrerenderingState PageLoadTracker::GetPrerenderingState() const { … }
std::optional<base::TimeDelta> PageLoadTracker::GetActivationStart() const { … }
const UserInitiatedInfo& PageLoadTracker::GetUserInitiatedInfo() const { … }
const GURL& PageLoadTracker::GetUrl() const { … }
const GURL& PageLoadTracker::GetStartUrl() const { … }
bool PageLoadTracker::DidCommit() const { … }
PageEndReason PageLoadTracker::GetPageEndReason() const { … }
const UserInitiatedInfo& PageLoadTracker::GetPageEndUserInitiatedInfo() const { … }
std::optional<base::TimeDelta> PageLoadTracker::GetTimeToPageEnd() const { … }
const base::TimeTicks& PageLoadTracker::GetPageEndTime() const { … }
const mojom::FrameMetadata& PageLoadTracker::GetMainFrameMetadata() const { … }
const mojom::FrameMetadata& PageLoadTracker::GetSubframeMetadata() const { … }
const PageRenderData& PageLoadTracker::GetPageRenderData() const { … }
const NormalizedCLSData& PageLoadTracker::GetNormalizedCLSData(
BfcacheStrategy bfcache_strategy) const { … }
const NormalizedCLSData&
PageLoadTracker::GetSoftNavigationIntervalNormalizedCLSData() const { … }
const ResponsivenessMetricsNormalization&
PageLoadTracker::GetResponsivenessMetricsNormalization() const { … }
const ResponsivenessMetricsNormalization&
PageLoadTracker::GetSoftNavigationIntervalResponsivenessMetricsNormalization()
const { … }
const mojom::InputTiming& PageLoadTracker::GetPageInputTiming() const { … }
const std::optional<blink::SubresourceLoadMetrics>&
PageLoadTracker::GetSubresourceLoadMetrics() const { … }
const PageRenderData& PageLoadTracker::GetMainFrameRenderData() const { … }
const ui::ScopedVisibilityTracker& PageLoadTracker::GetVisibilityTracker()
const { … }
const ResourceTracker& PageLoadTracker::GetResourceTracker() const { … }
const LargestContentfulPaintHandler&
PageLoadTracker::GetLargestContentfulPaintHandler() const { … }
const LargestContentfulPaintHandler&
PageLoadTracker::GetExperimentalLargestContentfulPaintHandler() const { … }
ukm::SourceId PageLoadTracker::GetPageUkmSourceId() const { … }
mojom::SoftNavigationMetrics& PageLoadTracker::GetSoftNavigationMetrics()
const { … }
ukm::SourceId PageLoadTracker::GetUkmSourceIdForSoftNavigation() const { … }
ukm::SourceId PageLoadTracker::GetPreviousUkmSourceIdForSoftNavigation() const { … }
bool PageLoadTracker::IsFirstNavigationInWebContents() const { … }
bool PageLoadTracker::IsOriginVisit() const { … }
bool PageLoadTracker::IsTerminalVisit() const { … }
int64_t PageLoadTracker::GetNavigationId() const { … }
void PageLoadTracker::RecordLinkNavigation() { … }
void PageLoadTracker::OnEnterBackForwardCache() { … }
void PageLoadTracker::OnRestoreFromBackForwardCache(
content::NavigationHandle* navigation_handle) { … }
void PageLoadTracker::OnV8MemoryChanged(
const std::vector<MemoryUpdate>& memory_updates) { … }
void PageLoadTracker::OnSharedStorageWorkletHostCreated() { … }
void PageLoadTracker::OnSharedStorageSelectURLCalled() { … }
void PageLoadTracker::OnAdAuctionComplete(bool is_server_auction,
bool is_on_device_auction,
content::AuctionResult result) { … }
void PageLoadTracker::UpdateMetrics(
content::RenderFrameHost* render_frame_host,
mojom::PageLoadTimingPtr timing,
mojom::FrameMetadataPtr metadata,
const std::vector<blink::UseCounterFeature>& features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr cpu_timing,
mojom::InputTimingPtr input_timing_delta,
const std::optional<blink::SubresourceLoadMetrics>&
subresource_load_metrics,
mojom::SoftNavigationMetricsPtr soft_navigation_metrics) { … }
void PageLoadTracker::AddCustomUserTimings(
std::vector<mojom::CustomUserTimingMarkPtr> custom_timings) { … }
void PageLoadTracker::SetPageMainFrame(content::RenderFrameHost* rfh) { … }
base::WeakPtr<PageLoadTracker> PageLoadTracker::GetWeakPtr() { … }
void PageLoadTracker::InvokeAndPruneObservers(
const char* trace_name,
PageLoadTracker::InvokeCallback callback,
bool permit_forwarding) { … }
}