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
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_THROTTLE_REGISTRY_IMPL_H_
#define CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_THROTTLE_REGISTRY_IMPL_H_
#include <optional>
#include <memory>
#include <set>
#include <vector>
#include "base/memory/raw_ref.h"
#include "base/memory/safety_checks.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/navigation_throttle_registry.h"
namespace content {
class NavigationHandle;
class NavigationRequest;
class NavigationThrottleRunner;
// The different event types that can be processed by NavigationThrottles.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// This type is also used in the UKM as set in the RecordDeferTimeUKM().
//
// LINT.IfChange(NavigationThrottleEvent)
enum class NavigationThrottleEvent {
kNoEvent = 0,
kWillStartRequest = 1,
kWillRedirectRequest = 2,
kWillFailRequest = 3,
kWillProcessResponse = 4,
kWillCommitWithoutUrlLoader = 5,
kMaxValue = kWillCommitWithoutUrlLoader,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/navigation/enums.xml:NavigationThrottleEvent)
// This is an abstract class that collaborates with
// NavigationThrottleRegistryBase that owns the set of NavigationThrottles added
// to an underlying navigation, and is responsible for calling the various sets
// of events on its NavigationThrottles, and notifying its delegate about the
// results of said events.
class NavigationThrottleRunnerBase {
public:
virtual ~NavigationThrottleRunnerBase() = default;
// Will call the appropriate NavigationThrottle function based on `event` on
// all NavigationThrottles owned by this NavigationThrottleRunner.
virtual void ProcessNavigationEvent(NavigationThrottleEvent event) = 0;
// Resumes calling the appropriate NavigationThrottle functions for the
// current processing event on all NavigationThrottles that have not yet been
// notified.
// `resuming_throttle` is the NavigationThrottle that asks for navigation
// event processing to be resumed; it should be the one currently deferring
// the navigation.
virtual void ResumeProcessingNavigationEvent(
NavigationThrottle* resuming_throttle) = 0;
};
class CONTENT_EXPORT NavigationThrottleRegistryBase
: public NavigationThrottleRegistry {
public:
~NavigationThrottleRegistryBase() override;
// Called when the NavigationThrottleRunner is done processing the navigation
// event of type `event`. `result` is the final
// NavigationThrottle::ThrottleCheckResult for this event.
virtual void OnEventProcessed(
NavigationThrottleEvent event,
NavigationThrottle::ThrottleCheckResult result) = 0;
// Called when the NavigationThrottleRunner is about to defer the navigation
// per a request from the given `deferring_throttle`.
virtual void OnDeferProcessingNavigationEvent(
NavigationThrottle* deferring_throttle) = 0;
// Returns the list of NavigationThrottles registered for this navigation.
virtual std::vector<std::unique_ptr<NavigationThrottle>>& GetThrottles() = 0;
// Returns the NavigationThrottle at the given `index`. The `index` should
// be in a valid range.
virtual NavigationThrottle& GetThrottleAtIndex(size_t index) = 0;
// Returns the throttles that are currently deferring the navigation.
virtual const std::set<NavigationThrottle*>& GetDeferringThrottles()
const = 0;
};
class CONTENT_EXPORT NavigationThrottleRegistryImpl
: public NavigationThrottleRegistryBase {
// Do not remove this macro!
// The macro is maintained by the memory safety team.
ADVANCED_MEMORY_SAFETY_CHECKS();
public:
explicit NavigationThrottleRegistryImpl(
NavigationRequest* navigation_request);
NavigationThrottleRegistryImpl(const NavigationThrottleRegistryImpl&) =
delete;
NavigationThrottleRegistryImpl& operator=(
const NavigationThrottleRegistryImpl&) = delete;
~NavigationThrottleRegistryImpl() override;
// Registers the appropriate NavigationThrottles for a "standard" navigation
// (i.e., one with a URLLoader that goes through the
// WillSendRequest/WillProcessResponse callback sequence).
void RegisterNavigationThrottles();
// Registers the appropriate NavigationThrottles for a navigation that can
// immediately commit because no URLLoader is required (about:blank,
// about:srcdoc, and most same-document navigations).
void RegisterNavigationThrottlesForCommitWithoutUrlLoader();
// Will call the appropriate NavigationThrottle function based on `event` on
// all NavigationThrottles owned by this registry.
void ProcessNavigationEvent(NavigationThrottleEvent event);
// Unblocks the NavigationRequest that was deferred by `resuming_throttle`.
// Once the NavigationThrottleRunner2 is enabled, multiple throttles may ask
// to defer the navigation for the same NavigationThrottleEvent. The
// underlying NavigationRequest will be resumed after all the throttles that
// deferred the navigation have unblocked the navigation.
void ResumeProcessingNavigationEvent(NavigationThrottle* resuiming_throttle);
// Sets a callback to be called when the navigation is deferred for the first
// time.
void SetFirstDeferralCallbackForTesting(base::OnceClosure callback);
// Implements NavigationThrottleRegistry:
NavigationHandle& GetNavigationHandle() override;
void AddThrottle(
std::unique_ptr<NavigationThrottle> navigation_throttle) override;
bool HasThrottle(const std::string& name) override;
bool EraseThrottleForTesting(const std::string& name) override;
bool IsHTTPOrHTTPS() override;
// Implements NavigationThrottleRegistryBase:
void OnEventProcessed(
NavigationThrottleEvent event,
NavigationThrottle::ThrottleCheckResult result) override;
std::vector<std::unique_ptr<NavigationThrottle>>& GetThrottles() override;
void OnDeferProcessingNavigationEvent(
NavigationThrottle* deferring_throttle) override;
NavigationThrottle& GetThrottleAtIndex(size_t index) override;
const std::set<NavigationThrottle*>& GetDeferringThrottles() const override;
private:
// Holds a reference to the NavigationRequest that owns this instance.
const raw_ref<NavigationRequest> navigation_request_;
// Owns the NavigationThrottles associated with this navigation, and is
// responsible for notifying them about the various navigation events.
std::unique_ptr<NavigationThrottleRunnerBase> navigation_throttle_runner_;
// A list of Throttles registered for this navigation.
std::vector<std::unique_ptr<NavigationThrottle>> throttles_;
// The throttles that are currently deferring the navigation.
std::set<NavigationThrottle*> deferring_throttles_;
// This is used in an experiment to cache frequently used navigation
// attributes.
// TODO(https://424460302): Remove this once the experiment completes, and
// move the cache to GURL if it's successful.
std::optional<bool> is_http_or_https_;
// A callback to be called when the navigation is deferred for the first time.
base::OnceClosure first_deferral_callback_for_testing_;
base::WeakPtrFactory<NavigationThrottleRegistryImpl> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_THROTTLE_REGISTRY_IMPL_H_
|