1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
#include <memory>
#include <optional>
#include <set>
#include "base/scoped_observation.h"
#include "components/page_load_metrics/common/page_load_timing.h"
#include "components/page_load_metrics/renderer/page_resource_data_use.h"
#include "components/page_load_metrics/renderer/page_timing_metadata_recorder.h"
#include "content/public/renderer/render_frame_observer.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
#include "third_party/blink/public/common/subresource_load_metrics.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
#include "third_party/blink/public/web/web_local_frame_observer.h"
class GURL;
namespace base {
class OneShotTimer;
} // namespace base
namespace blink {
struct JavaScriptFrameworkDetectionResult;
struct SoftNavigationMetrics;
} // namespace blink
namespace page_load_metrics {
namespace internal {
const char kPageLoadInternalSoftNavigationFromStartInvalidTiming[] =
"PageLoad.Internal.SoftNavigationFromStartInvalidTiming";
// These values are recorded into a UMA histogram as scenarios where the start
// time of soft navigation ends up being 0. These entries
// should not be renumbered and the numeric values should not be reused. These
// entries should be kept in sync with the definition in
// tools/metrics/histograms/enums.xml
// TODO(crbug.com/40074158): Remove the code here and related code once the bug
// is resolved.
enum class SoftNavigationFromStartInvalidTimingReasons {
kSoftNavStartTimeIsZeroAndLtNavStart = 0,
kSoftNavStartTimeIsZeroAndEqNavStart = 1,
kSoftNavStartTimeIsNonZeroAndEqNavStart = 2,
kSoftNavStartTimeIsNonZeroAndLtNavStart = 3,
kMaxValue = kSoftNavStartTimeIsNonZeroAndLtNavStart,
};
void RecordUmaForkPageLoadInternalSoftNavigationFromStartInvalidTiming(
base::TimeDelta start_time_relative_to_reference,
double nav_start_to_reference);
} // namespace internal
class PageTimingMetricsSender;
class PageTimingSender;
// MetricsRenderFrameObserver observes RenderFrame notifications, and sends page
// load timing information to the browser process over IPC. A
// MetricsRenderFrameObserver is instantiated for each frame (main frames and
// child frames). MetricsRenderFrameObserver dispatches timing and metadata
// updates for main frames, but only metadata updates for child frames.
class MetricsRenderFrameObserver : public content::RenderFrameObserver,
public blink::WebLocalFrameObserver {
public:
explicit MetricsRenderFrameObserver(content::RenderFrame* render_frame);
MetricsRenderFrameObserver(const MetricsRenderFrameObserver&) = delete;
MetricsRenderFrameObserver& operator=(const MetricsRenderFrameObserver&) =
delete;
~MetricsRenderFrameObserver() override;
// RenderFrameObserver implementation
void DidChangePerformanceTiming() override;
void DidObserveUserInteraction(base::TimeTicks max_event_start,
base::TimeTicks max_event_queued_main_thread,
base::TimeTicks max_event_commit_finish,
base::TimeTicks max_event_end,
uint64_t interaction_offset) override;
void DidChangeCpuTiming(base::TimeDelta time) override;
void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override;
void DidObserveJavaScriptFrameworks(
const blink::JavaScriptFrameworkDetectionResult&) override;
void DidObserveSubresourceLoad(
const blink::SubresourceLoadMetrics& subresource_load_metrics) override;
void DidObserveNewFeatureUsage(
const blink::UseCounterFeature& feature) override;
void DidObserveSoftNavigation(blink::SoftNavigationMetrics metrics) override;
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
void DidStartResponse(const url::SchemeHostPort& final_response_url,
int request_id,
const network::mojom::URLResponseHead& response_head,
network::mojom::RequestDestination request_destination,
bool is_ad_resource) override;
void DidReceiveTransferSizeUpdate(int request_id,
int received_data_length) override;
void DidCompleteResponse(
int request_id,
const network::URLLoaderCompletionStatus& status) override;
void DidCancelResponse(int request_id) override;
void DidLoadResourceFromMemoryCache(const GURL& response_url,
int request_id,
int64_t encoded_body_length,
const std::string& mime_type,
bool from_archive) override;
void DidStartNavigation(
const GURL& url,
std::optional<blink::WebNavigationType> navigation_type) override;
void DidSetPageLifecycleState(bool restoring_from_bfcache) override;
void ReadyToCommitNavigation(
blink::WebDocumentLoader* document_loader) override;
void DidFailProvisionalLoad() override;
void DidCommitProvisionalLoad(ui::PageTransition transition) override;
void DidCreateDocumentElement() override;
void OnDestruct() override;
// Invoked when a frame is going away. This is our last chance to send IPCs
// before being destroyed.
void WillDetach(blink::DetachReason detach_reason) override;
void OnMainFrameIntersectionChanged(
const gfx::Rect& main_frame_intersection_rect) override;
void OnMainFrameViewportRectangleChanged(
const gfx::Rect& main_frame_viewport_rect) override;
void OnMainFrameImageAdRectangleChanged(
int element_id,
const gfx::Rect& image_ad_rect) override;
// blink::WebLocalFrameObserver implementation
void OnFrameDetached() override;
bool SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion& shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion& shared_memory_dropped_frames) override;
protected:
// The relative and monotonic page load timings.
struct Timing {
Timing(mojom::PageLoadTimingPtr relative_timing,
const PageTimingMetadataRecorder::MonotonicTiming& monotonic_timing);
~Timing();
Timing(const Timing&) = delete;
Timing& operator=(const Timing&) = delete;
Timing(Timing&&);
Timing& operator=(Timing&&);
mojom::PageLoadTimingPtr relative_timing;
PageTimingMetadataRecorder::MonotonicTiming monotonic_timing;
};
private:
// Updates the metadata for the page resource associated with the given
// request_id. Removes the request_id from the list of known ads if it is an
// ad.
void UpdateResourceMetadata(int request_id);
void SendMetrics();
void OnMetricsSenderCreated();
virtual Timing GetTiming() const;
virtual mojom::SoftNavigationMetricsPtr GetSoftNavigationMetrics() const;
virtual mojom::CustomUserTimingMarkPtr GetCustomUserTimingMark() const;
virtual std::unique_ptr<base::OneShotTimer> CreateTimer();
virtual std::unique_ptr<PageTimingSender> CreatePageTimingSender(
bool limited_sending_mode);
virtual bool HasNoRenderFrame() const;
virtual bool IsMainFrame() const;
// Collects the data use of the frame request for a provisional load until the
// load is committed. We want to collect data use for completed navigations in
// this class, but the various navigation callbacks do not provide enough data
// for us to use them for data attribution. Instead, we try to get this
// information from ongoing resource requests on the previous page (or right
// before this page loads in a new renderer).
std::unique_ptr<PageResourceDataUse> provisional_frame_resource_data_use_;
// Handle to the shared memory for transporting smoothness related ukm data.
base::ReadOnlySharedMemoryRegion ukm_smoothness_data_;
base::ReadOnlySharedMemoryRegion ukm_dropped_frames_data_;
// The main frame intersection rectangle signal received before
// `page_timing_metrics_sender_` is created. The signal will be send out right
// after `page_timing_metrics_sender_` is created.
std::optional<gfx::Rect>
main_frame_intersection_rect_before_metrics_sender_created_;
// Will be null when we're not actively sending metrics.
std::unique_ptr<PageTimingMetricsSender> page_timing_metrics_sender_;
};
} // namespace page_load_metrics
#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
|