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
|
// Copyright 2024 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_SUPERVISED_USER_CLASSIFY_URL_NAVIGATION_THROTTLE_H_
#define CHROME_BROWSER_SUPERVISED_USER_CLASSIFY_URL_NAVIGATION_THROTTLE_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/elapsed_timer.h"
#include "components/supervised_user/core/browser/supervised_user_url_filter.h"
#include "components/supervised_user/core/browser/supervised_user_utils.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "url/gurl.h"
namespace supervised_user {
// LINT.IfChange(ClassifyUrlThrottleFinalStatus)
enum class ClassifyUrlThrottleFinalStatus : int {
kAllowed = 0,
kBlocked = 1,
kMaxValue = kBlocked,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/families/enums.xml:ClassifyUrlThrottleFinalStatus)
// LINT.IfChange(ClassifyUrlThrottleStatus)
enum class ClassifyUrlThrottleStatus : int {
kContinue = 0,
kProceed = 1,
kDefer = 2,
kDeferAndScheduleInterstitial = 3,
kCancel = 4,
kResume = 5,
kCancelDeferredNavigation = 6,
kMaxValue = kCancelDeferredNavigation,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/families/enums.xml:ClassifyUrlThrottleStatus)
// LINT.IfChange(ClassifyUrlThrottleUseCase)
enum class ClassifyUrlThrottleUseCase : int {
kNotAllowed = 0,
kFamilyLinkSupervisedUser = 1,
kMaxValue = kFamilyLinkSupervisedUser,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/families/enums.xml:ClassifyUrlThrottleUseCase)
enum class InterstitialResultCallbackActions {
kCancelNavigation = 0,
kCancelWithInterstitial = 1
};
// Returns a new throttle for the given navigation, or nullptr if no
// throttling is required.
void MaybeCreateAndAddClassifyUrlNavigationThrottle(
content::NavigationThrottleRegistry& registry);
// Navigation throttle that processes requests and redirects in parallel with
// their verification against ClassifyUrl, up until the response is ready for
// processing. Only then the navigation can be deferred.
class ClassifyUrlNavigationThrottle : public content::NavigationThrottle {
public:
static void CreateAndAdd(content::NavigationThrottleRegistry& registry,
SupervisedUserURLFilter* url_filter);
ClassifyUrlNavigationThrottle(const ClassifyUrlNavigationThrottle&) = delete;
ClassifyUrlNavigationThrottle& operator=(
const ClassifyUrlNavigationThrottle&) = delete;
~ClassifyUrlNavigationThrottle() override;
protected:
void CancelDeferredNavigation(ThrottleCheckResult result) override;
private:
// Smart container that manages list of pending checks and derives overall
// verdict for the throttle. The checks are stored in the order in which they
// were scheduled. The list can be sealed (marked that no more checks will be
// scheduled) which is important to determine the final verdict.
class ClassifyUrlCheckList {
public:
using Key = std::vector<SupervisedUserURLFilter::Result>::size_type;
ClassifyUrlCheckList();
ClassifyUrlCheckList(ClassifyUrlCheckList& other) = delete;
const ClassifyUrlCheckList& operator=(ClassifyUrlCheckList& other) = delete;
~ClassifyUrlCheckList();
// Registers new check if the list is not sealed.
Key NewCheck();
void UpdateCheck(Key key, SupervisedUserURLFilter::Result result);
// Returns blocking Filtering result if there's one or nothing.
std::optional<SupervisedUserURLFilter::Result> GetBlockingResult() const;
// Returns true if this classification allowed or blocking.
bool IsDecided() const;
// Seals this instance. After calling this method `NewCheck` cannot be
// called, but behavior of `IsDecided()` changes.
void MarkNavigationRequestsCompleted();
base::TimeDelta ElapsedSinceDecided() const;
private:
std::vector<std::optional<SupervisedUserURLFilter::Result>> results_;
// After disabling new checks can't be issued, but it enables positive
// verification of all-allow results.
bool new_checks_disabled_{false};
// Tracks time from being updated by the most recent result that had effect
// on verdict.
std::optional<base::ElapsedTimer> elapsed_;
};
ClassifyUrlNavigationThrottle(content::NavigationThrottleRegistry& registry,
SupervisedUserURLFilter* url_filter);
// content::NavigationThrottle implementation:
ThrottleCheckResult WillStartRequest() override;
ThrottleCheckResult WillRedirectRequest() override;
ThrottleCheckResult WillProcessResponse() override;
const char* GetNameForLogging() override;
// Common procedure for both initial request and redirects.
ThrottleCheckResult WillProcessRequest();
// The URL the frame is navigating to. This may change during the navigation
// when encountering a server redirect.
const GURL& currently_navigated_url() const;
// Triggers a URL check; the result might be processed either synchronously
// or asynchronously.
void CheckURL();
// The triggered callback; results will be written onto check.
void OnURLCheckDone(ClassifyUrlCheckList::Key key,
SupervisedUserURLFilter::Result result);
// Change state of the throttle and record metrics.
std::optional<ThrottleCheckResult> NextNavigationState(
ClassifyUrlThrottleStatus status);
// Defers the navigation to accommodate the interstitial and shows that
// interstitial.
ThrottleCheckResult DeferAndScheduleInterstitial(
SupervisedUserURLFilter::Result result);
// Interstitial handling
void ScheduleInterstitial(SupervisedUserURLFilter::Result result);
void ShowInterstitial(SupervisedUserURLFilter::Result result);
void OnInterstitialResult(SupervisedUserURLFilter::Result result,
InterstitialResultCallbackActions action,
bool already_sent_request,
bool is_main_frame);
// All pending and completed checks.
ClassifyUrlCheckList list_;
// True iff one of navigation events returned ::DEFER.
bool deferred_{false};
// Timers forming a continuum of time, only recorded in unblocked navigation
// (success) case.
std::optional<base::ElapsedTimer> waiting_for_decision_;
raw_ptr<SupervisedUserURLFilter> url_filter_;
base::WeakPtrFactory<ClassifyUrlNavigationThrottle> weak_ptr_factory_{this};
};
} // namespace supervised_user
#endif // CHROME_BROWSER_SUPERVISED_USER_CLASSIFY_URL_NAVIGATION_THROTTLE_H_
|