blob: 8a0ff5c716cfe562fb8e3b8297d5510812ba8fa5 [file] [log] [blame]
// 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 <list>
#include <memory>
#include <optional>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/supervised_user/supervised_user_navigation_throttle.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(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)
// Returns a new throttle for the given navigation, or nullptr if no
// throttling is required.
std::unique_ptr<content::NavigationThrottle>
MaybeCreateClassifyUrlNavigationThrottleFor(
content::NavigationHandle* navigation_handle);
// 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 std::unique_ptr<ClassifyUrlNavigationThrottle> MakeUnique(
content::NavigationHandle* navigation_handle);
ClassifyUrlNavigationThrottle(const ClassifyUrlNavigationThrottle&) = delete;
ClassifyUrlNavigationThrottle& operator=(
const ClassifyUrlNavigationThrottle&) = delete;
~ClassifyUrlNavigationThrottle() override;
protected:
void CancelDeferredNavigation(ThrottleCheckResult result) override;
private:
explicit ClassifyUrlNavigationThrottle(
content::NavigationHandle* navigation_handle);
// Named tuple for bits of result.
struct CheckResult {
FilteringBehavior behavior;
FilteringBehaviorReason reason;
};
// Represents a check. For checks in flight, result is nullopt.
struct Check {
GURL url;
std::optional<CheckResult> result;
};
// 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;
// Verdict is decided if either:
// * all checks resulted in kAllow
// * a prefix of checks resulted in kAllow followed by a kBlock
// Verdict is not decided otherwise, if there's a kInvalid not preceded by
// kBlock
// Examples:
// * kAllow, kAllow, kAllow is decided,
// * kAllow, kAllow, kBlock is decided,
// * kAllow, kBlock, kInvalid is decided,
// * kAllow, kAllow, kInvalid is not decided (might be allow or block),
// * kAllow, kInvalid, kBlock is not decided (unsure what redirect is a
// block).
bool IsDecided() const;
// Iterator pointing at first blocking verdict if it's defined, or ::cend()
// otherwise.
std::list<Check>::const_iterator FirstBlockingCheck() const;
// Updates the pending_check item with matching check (by url field).
void SetCheck(const GURL& url, const CheckResult& result);
// Triggers a URL check; the result might be processed either synchronously
// or asynchronously.
void CheckURL();
void OnURLCheckDone(const GURL& url,
FilteringBehavior behavior,
FilteringBehaviorReason reason,
bool uncertain);
// 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(Check check);
// Interstitial handling
void ScheduleInterstitial(Check check);
void ShowInterstitial(Check check);
void OnInterstitialResult(
Check check,
SupervisedUserNavigationThrottle::CallbackActions action,
bool already_sent_request,
bool is_main_frame);
// Ordered list of pending and completed checks.
std::list<Check> checks_;
// 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_;
std::optional<base::ElapsedTimer> waiting_for_process_response_;
raw_ptr<supervised_user::SupervisedUserURLFilter> url_filter_;
base::WeakPtrFactory<ClassifyUrlNavigationThrottle> weak_ptr_factory_{this};
};
} // namespace supervised_user
#endif // CHROME_BROWSER_SUPERVISED_USER_CLASSIFY_URL_NAVIGATION_THROTTLE_H_