[go: nahoru, domu]

blob: 62b03ce8c7830b796e6d6d8af7694a8a7f2d007c [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_CORE_AMP_PAGE_LOAD_METRICS_OBSERVER_H_
#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_CORE_AMP_PAGE_LOAD_METRICS_OBSERVER_H_
#include <map>
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "components/page_load_metrics/browser/layout_shift_normalization.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
#include "components/page_load_metrics/browser/responsiveness_metrics_normalization.h"
#include "services/metrics/public/cpp/ukm_source.h"
namespace content {
class NavigationHandle;
}
namespace ukm {
namespace builders {
class AmpPageLoad;
} // namespace builders
} // namespace ukm
// Observer responsible for recording metrics for AMP documents. This includes
// both AMP documents loaded in the main frame, and AMP documents loaded in a
// subframe (e.g. in an AMP viewer in the main frame).
//
// For AMP documents loaded in a subframe, recording works like so:
//
// * whenever the main frame URL gets updated with an AMP viewer
// URL (e.g. https://www.google.com/amp/...), we track that in
// OnCommitSameDocumentNavigation. we use the time of the main
// frame URL update as the baseline time from which the
// user-perceived performance metrics like FCP are computed.
//
// * whenever an iframe AMP document is loaded, we track that in
// OnDidFinishSubFrameNavigation. we also keep track of the
// performance timing metrics such as FCP reported in the frame.
//
// * we associate the main frame AMP navigation with its associated
// AMP document in an iframe by comparing URLs between the main
// frame and the iframe documents.
//
// * we record AMP metrics at the times when an AMP viewer URL is
// navigated away from. when a user swipes to change the AMP
// document, closes a tab, types a new URL in the URL bar, etc,
// we will record AMP metrics for the AMP doc in an iframe that
// the user is navigating away from.
class AMPPageLoadMetricsObserver
: public page_load_metrics::PageLoadMetricsObserver {
public:
AMPPageLoadMetricsObserver();
AMPPageLoadMetricsObserver(const AMPPageLoadMetricsObserver&) = delete;
AMPPageLoadMetricsObserver& operator=(const AMPPageLoadMetricsObserver&) =
delete;
~AMPPageLoadMetricsObserver() override;
// page_load_metrics::PageLoadMetricsObserver:
ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
ukm::SourceId source_id) override;
void OnCommitSameDocumentNavigation(
content::NavigationHandle* navigation_handle) override;
void OnDidFinishSubFrameNavigation(
content::NavigationHandle* navigation_handle) override;
void OnRenderFrameDeleted(content::RenderFrameHost* rfh) override;
void OnTimingUpdate(
content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::PageLoadTiming& timing) override;
void OnInputTimingUpdate(
content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::InputTiming& input_timing_delta) override;
void OnMobileFriendlinessUpdate(
const blink::MobileFriendliness& mobile_friendliness) override;
void OnSubFrameRenderDataUpdate(
content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::FrameRenderDataUpdate& render_data)
override;
void OnComplete(
const page_load_metrics::mojom::PageLoadTiming& timing) override;
void OnLoadingBehaviorObserved(content::RenderFrameHost* subframe_rfh,
int behavior_flags) override;
private:
// Information about an AMP navigation in the main frame. Both regular and
// same document navigations are included.
struct MainFrameNavigationInfo {
GURL url;
ukm::SourceId ukm_source_id = ukm::kInvalidSourceId;
// Pointer to the RenderViewHost for the iframe hosting the AMP document
// associated with the main frame AMP navigation.
raw_ptr<content::RenderFrameHost> subframe_rfh = nullptr;
// Navigation start time for the main frame AMP navigation. We use this time
// as an approximation of the time the user initiated the navigation.
base::TimeTicks navigation_start;
// Whether the main frame navigation is a same document navigation.
bool is_same_document_navigation = false;
};
// Information about an AMP subframe.
struct SubFrameInfo {
SubFrameInfo();
~SubFrameInfo();
// The AMP viewer URL of the currently committed AMP document. Used for
// matching the MainFrameNavigationInfo url.
GURL viewer_url;
// The navigation start time of the non-same-document navigation in the AMP
// iframe. Timestamps in |timing| below are relative to this value.
base::TimeTicks navigation_start;
// Performance metrics observed in the AMP iframe.
page_load_metrics::mojom::PageLoadTimingPtr timing;
page_load_metrics::PageRenderData render_data;
page_load_metrics::LayoutShiftNormalization layout_shift_normalization;
page_load_metrics::ResponsivenessMetricsNormalization
responsiveness_metrics_normalization;
// MobileFriendliness metrics observed in the AMP iframe.
blink::MobileFriendliness mobile_friendliness;
// Whether an AMP document was loaded, based on observed
// LoadingBehaviorFlags for this frame.
bool amp_document_loaded = false;
};
void RecordLoadingBehaviorObserved();
void RecordNormalizedResponsivenessMetrics(
const page_load_metrics::NormalizedResponsivenessMetrics&
normalized_responsiveness_metrics,
ukm::builders::AmpPageLoad& builder);
void ProcessMainFrameNavigation(content::NavigationHandle* navigation_handle);
void MaybeRecordAmpDocumentMetrics();
void RecordMobileFriendliness(ukm::builders::AmpPageLoad& builder);
// Information about the currently active AMP navigation in the main
// frame. Will be null if there isn't an active AMP navigation in the main
// frame.
std::unique_ptr<MainFrameNavigationInfo> current_main_frame_nav_info_;
// Information about each active AMP iframe in the main document.
std::map<content::RenderFrameHost*, SubFrameInfo> amp_subframe_info_;
GURL current_url_;
bool observed_amp_main_frame_ = false;
bool observed_amp_sub_frame_ = false;
};
#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_CORE_AMP_PAGE_LOAD_METRICS_OBSERVER_H_