blob: 599ced61fc82c747661081e7866f0040144e3fc8 [file] [log] [blame]
// 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_PUBLIC_BROWSER_PROCESS_SELECTION_DEFERRING_CONDITION_H_
#define CONTENT_PUBLIC_BROWSER_PROCESS_SELECTION_DEFERRING_CONDITION_H_
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/safe_ref.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_handle.h"
namespace content {
class NavigationHandle;
class ProcessSelectionUserData;
// Base class to allow clients to prepare inputs that are needed for selecting a
// process during a navigation request, optionally deferring the final process
// selection when necessary. On creation, the implementing class can begin to
// prepare results for the associated NavigationHandle by queuing asynchronous
// tasks. The `ProcessSelectionDeferringCondition` will be notified at
// `NavigationRequest::OnRequestRedirected()` time, giving the class an
// opportunity to schedule additional tasks, or cancel previously queued ones.
// Then, after the network response is received, the navigation will call
// `OnWillSelectFinalProcess()`. At this time, the class can defer by returning
// `Result::kDefer`. If it returns `Result::kDefer`, then it must call the
// provided resume closure in order for the navigation to proceed. Once all
// conditions have resumed, navigation continues from
// `NavigationRequest::SelectFrameHostForOnResponseStarted()`.
//
// `ProcessSelectionDeferringCondition` vs. `NavigationThrottle` and
// `CommitDeferringCondition`: It may seem like either a `NavigationThrottle` or
// a `CommitDeferringCondition` could be used to provide the same functionality
// by deferring in `NavigationThrottle::WillProcessResponse` or
// `CommitDeferringCondition::WillCommitNavigation`, however those hooks occur
// after process selection has been finalized. Another key difference between
// these mechanisms is that `ProcessSelectionDeferringCondition` can only defer
// and is unable to cancel or otherwise influence the navigation request. Most
// potential clients will want to use the `NavigationThrottle` or the
// `CommitDeferringCondition` mechanism for their use-case.
class CONTENT_EXPORT ProcessSelectionDeferringCondition {
public:
enum class Result {
// Returned when the condition is satisfied and the client can synchronously
// proceed with process selection.
kProceed,
// Returned when the condition needs to asynchronously wait before allowing
// process selection to occur.
kDefer,
};
ProcessSelectionDeferringCondition() = delete;
explicit ProcessSelectionDeferringCondition(
NavigationHandle& navigation_handle);
ProcessSelectionDeferringCondition(
const ProcessSelectionDeferringCondition& other) = delete;
ProcessSelectionDeferringCondition& operator=(
const ProcessSelectionDeferringCondition& other) = delete;
virtual ~ProcessSelectionDeferringCondition();
// Called when the navigation request is redirected. This should handle
// canceling any currently running tasks that are no longer needed, as well as
// starting new tasks for the redirected request.
virtual void OnRequestRedirected() {}
// Called when the navigation request will select the renderer host process.
// If the condition is ready, return `Result::kProceed` so that the navigation
// can continue with selecting a final SiteInstance and process; otherwise
// return `Result::kDefer`. When `kDefer` is returned, the navigation will
// block until the passed in resume closure is called. NOTE: Avoid deferring
// whenever possible because this slows page loads. See the comment in
// NavigationThrottle::ThrottleAction::DEFER for more information.
virtual Result OnWillSelectFinalProcess(base::OnceClosure resume) = 0;
NavigationHandle& navigation_handle() const { return *navigation_handle_; }
// A convenience method to get the ProcessSelectionUserData instance
// associated with this navigation. Implementers of this class can use this
// data container to attach any relevant information that needs to be made
// available to the process selection logic. See `ProcessSelectionUserData`
// for details about defining and retrieving custom data.
ProcessSelectionUserData& GetProcessSelectionUserData() {
return navigation_handle_->GetProcessSelectionUserData();
}
private:
base::SafeRef<NavigationHandle> navigation_handle_;
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_PROCESS_SELECTION_DEFERRING_CONDITION_H_