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 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PREDICTORS_LOADING_DATA_COLLECTOR_H_
#define CHROME_BROWSER_PREDICTORS_LOADING_DATA_COLLECTOR_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/types/id_type.h"
#include "chrome/browser/predictors/loading_predictor_config.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/fetch_api.mojom-forward.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-forward.h"
#include "url/gurl.h"
#include "url/origin.h"
// base::flat_set is O(n), limit to a reasonable history length
#define MAX_PREDICTOR_SUBRESOURCE_URL_HISTORY 4096
namespace content {
class NavigationHandle;
} // namespace content
namespace predictors {
class LoadingStatsCollector;
struct OptimizationGuidePrediction;
class ResourcePrefetchPredictor;
using NavigationId = base::IdType64<content::NavigationHandle>;
// Data collected for origin-based prediction, for a single origin during a
// page load (see PageRequestSummary).
struct OriginRequestSummary {
OriginRequestSummary();
OriginRequestSummary(const OriginRequestSummary& other);
~OriginRequestSummary();
url::Origin origin;
bool always_access_network = false;
bool accessed_network = false;
int first_occurrence = 0;
};
// Stores the data learned from a single navigation.
struct PageRequestSummary {
PageRequestSummary(ukm::SourceId ukm_source_id,
const GURL& main_frame_url,
base::TimeTicks navigation_started);
PageRequestSummary(const PageRequestSummary& other);
~PageRequestSummary();
void UpdateOrAddResource(
const blink::mojom::ResourceLoadInfo& resource_load_info);
void AddPreconnectAttempt(const GURL& preconnect_url);
void AddPrefetchAttempt(const GURL& prefetch_url);
void MainFrameLoadComplete();
const ukm::SourceId ukm_source_id;
GURL main_frame_url;
const GURL initial_url;
const base::TimeTicks navigation_started;
std::optional<base::TimeTicks> navigation_committed;
bool main_frame_load_complete{false};
// Map of origin -> OriginRequestSummary. Only one instance of each origin
// is kept per navigation, but the summary is updated several times.
std::map<url::Origin, OriginRequestSummary> origins;
// Set of origins for which preconnects were initiated.
base::flat_set<url::Origin> preconnect_origins;
// Set of seen resource URLs.
base::flat_set<GURL> subresource_urls;
// Set of resource URLs for which prefetches were initiated.
base::flat_set<GURL> prefetch_urls;
// The time for which the first resource prefetch was initiated for the
// navigation.
std::optional<base::TimeTicks> first_prefetch_initiated;
// Equivalents of |origins_| and |subresource_urls| that store URLs/origins
// that are not learned by LoadingPredictor. These are from low-priority
// subresource loads, or subresource loads after the load event for the page
// has been dispatched. They are used to record metrics to understand the
// precision of optimization guide predictions.
base::flat_set<url::Origin> low_priority_origins;
base::flat_set<GURL> low_priority_subresource_urls;
private:
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, HandledResourceTypes);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ShouldRecordMainFrameLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoadAfterFCP);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoadAfterLoadComplete);
enum ShouldRecordResourceLoadResult { kNo, kLowPriority, kYes };
ShouldRecordResourceLoadResult ShouldRecordResourceLoad(
const blink::mojom::ResourceLoadInfo& resource_load_info) const;
// Returns true if the resource has a supported type.
static bool IsHandledResourceType(
network::mojom::RequestDestination destination,
const std::string& mime_type);
void UpdateOrAddToOrigins(
const url::Origin& origin,
const blink::mojom::CommonNetworkInfoPtr& network_info,
bool is_low_priority);
};
// Records navigation events as reported by various observers to the database
// and stats collection classes. All the non-static methods of this class need
// to be called on the UI thread.
class LoadingDataCollector {
public:
explicit LoadingDataCollector(
predictors::ResourcePrefetchPredictor* predictor,
predictors::LoadingStatsCollector* stats_collector,
const LoadingPredictorConfig& config);
virtual ~LoadingDataCollector();
// |LoadingPredictorTabHelper| calls the below functions to inform the
// collector of navigation and resource load events.
virtual void RecordStartNavigation(NavigationId navigation_id,
ukm::SourceId ukm_source_id,
const GURL& main_frame_url,
base::TimeTicks creation_time);
virtual void RecordFinishNavigation(NavigationId navigation_id,
const GURL& new_main_frame_url,
bool is_error_page);
virtual void RecordResourceLoadComplete(
NavigationId navigation_id,
const blink::mojom::ResourceLoadInfo& resource_load_info);
// Called when a preconnect is initiated for the navigation.
virtual void RecordPreconnectInitiated(NavigationId navigation_id,
const GURL& preconnect_url);
// Called when a prefetch is initiated for the navigation.
virtual void RecordPrefetchInitiated(NavigationId navigation_id,
const GURL& prefetch_url);
// Called when the main frame of a page completes loading. We treat this point
// as the "completion" of the navigation. The resources requested by the page
// up to this point are the only ones considered by |predictor_|.
virtual void RecordMainFrameLoadComplete(NavigationId navigation_id);
// Called when the page committed by the navigation is destroyed.
virtual void RecordPageDestroyed(
NavigationId navigation_id,
const std::optional<OptimizationGuidePrediction>& prediction);
private:
using NavigationMap =
std::map<NavigationId, std::unique_ptr<PageRequestSummary>>;
friend class LoadingDataCollectorTest;
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ShouldRecordMainFrameLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, SimpleNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, SimpleRedirect);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordStartNavigationMissing);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, RecordFailedNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ManyNavigations);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordResourceLoadComplete);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordPreconnectInitiatedNoInflightNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordPrefetchInitiatedNoInflightNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoadAfterLoadComplete);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, RecordPageDestroyed);
static void SetAllowPortInUrlsForTesting(bool state);
// Cleanup inflight_navigations_ and call a cleanup for stats_collector_.
void CleanupAbandonedNavigations();
const raw_ptr<ResourcePrefetchPredictor, DanglingUntriaged> predictor_;
const raw_ptr<LoadingStatsCollector> stats_collector_;
const LoadingPredictorConfig config_;
NavigationMap inflight_navigations_;
};
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_LOADING_DATA_COLLECTOR_H_
|