blob: 957a8971dd93d2595a432ffe64b55b3dac0c3490 [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 IOS_CHROME_BROWSER_PRERENDER_MODEL_PRERENDER_BROWSER_AGENT_H_
#define IOS_CHROME_BROWSER_PRERENDER_MODEL_PRERENDER_BROWSER_AGENT_H_
#import <Foundation/Foundation.h>
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "components/prefs/pref_change_registrar.h"
#include "ios/chrome/browser/prerender/model/prerender_pref.h"
#include "ios/chrome/browser/prerender/model/prerender_tab_helper_delegate.h"
#include "ios/chrome/browser/shared/model/browser/browser_user_data.h"
#include "ios/web/public/navigation/referrer.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
class ManageAccountsDelegate;
@protocol PrerenderBrowserAgentDelegate;
namespace web {
class WebState;
} // namespace web
// A BrowserAgent responsible for managing the pre-rendering of web pages.
class PrerenderBrowserAgent final
: public BrowserUserData<PrerenderBrowserAgent>,
public net::NetworkChangeNotifier::NetworkChangeObserver,
public PrerenderTabHelperDelegate {
public:
// Policy for starting pre-rendering.
enum PrerenderPolicy {
kNoDelay,
kDefaultDelay,
};
~PrerenderBrowserAgent() final;
// Sets the delegate that will provide information to this agent.
void SetDelegate(id<PrerenderBrowserAgentDelegate> delegate);
// Schedule prerendering for `url` with the given `transition` and `referrer`
// with delay based on `policy`.
//
// If there is already an existing request for `url`, this method does
// nothing and does not reset the delay. If there is an existing request
// for a different URL, it is cancelled before the new request is queued.
//
// Unless `policy` is `kNoDelay` the pre-rendering is only started after
// a short delay, to prevent unnecessary pre-rendering while the user is
// typing.
void StartPrerender(const GURL& url,
const web::Referrer& referrer,
ui::PageTransition transition,
PrerenderPolicy policy);
// Promotes the pre-rendered tab to a real tab, replacing the Browser's
// active WebState if it is used to pre-render `url`. Otherwise cancels
// the pre-rendering.
//
// Returns whether the active WebState was replaced or not.
bool ValidatePrerender(const GURL& url, ui::PageTransition transition);
// Returns whether a pre-rendered WebState is being inserted into the
// Browser by this agent.
bool IsInsertingPrerender() const;
// PrerenderTabHelperDelegate implementation.
void CancelPrerender() final;
private:
// Helper classes used to store information about prerender requests.
template <typename WebStatePtr>
class Request;
class RequestInfos;
// Helper classes that will implement the WebStateDelegate, WebStateObserver
// and WebStatePolicyDecider API respectively for PrerenderBrowserAgent.
class Delegate;
class Observer;
class PolicyDecider;
class ManageAccountsDelegate;
// Enumeration for pre-render termination reason.
enum class PrerenderFinalStatus;
friend class Delegate;
friend class Observer;
friend class PolicyDecider;
friend class ManageAccountsDelegate;
friend class BrowserUserData<PrerenderBrowserAgent>;
PrerenderBrowserAgent(Browser* browser);
// Returns whether pre-render is enabled or not.
bool Enabled() const;
// Returns whether `url` is already pre-rendered or there is a scheduled
// request to pre-render it.
bool IsPrerenderdOrScheduled(const GURL& url) const;
// Starts the pending request.
void StartPendingRequest();
// Schedule a call to cancel the pre-rendering on the next run loop.
void ScheduleCancelPrerender();
// Cancels any scheduled pre-render request. Does nothing if there is no
// requests scheduled.
void CancelScheduledRequest();
// Cancels the pre-render with `reason`.
void CancelPrerenderInternal(PrerenderFinalStatus reason);
// Destroys the pre-render with `reason`.
void DestroyPrerender(PrerenderFinalStatus reason);
// Releases the pre-render WebState with `reason`.
[[nodiscard]] std::unique_ptr<web::WebState> ReleasePrerender(
PrerenderFinalStatus reason);
// Called when the NetworkPredictionSetting value may have changed.
void OnNetworkPredictionSettingChanged();
// net::NetworkChangeNotifier::NetworkChangeObserver implementation.
void OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type) final;
SEQUENCE_CHECKER(sequence_checker_);
__weak id<PrerenderBrowserAgentDelegate> delegate_;
// Pending and in-progress pre-render requests.
std::unique_ptr<Request<base::WeakPtr<web::WebState>>> scheduled_request_;
std::unique_ptr<Request<std::unique_ptr<web::WebState>>> prerender_request_;
std::unique_ptr<Delegate> web_state_delegate_;
std::unique_ptr<Observer> web_state_observer_;
std::unique_ptr<PolicyDecider> policy_decider_;
// Used for all pre-renders.
std::unique_ptr<ManageAccountsDelegate> manage_accounts_delegate_;
// Used to schedule pre-render requests.
base::OneShotTimer timer_;
// Registration with the NSNotificationCenter.
__strong id<NSObject> nsnotification_registration_;
// Used to track the preferences and the network status.
PrefChangeRegistrar registrar_;
// Is the pre-render tab being converted to a real tab?
bool loading_prerender_ = false;
base::WeakPtrFactory<PrerenderBrowserAgent> weak_ptr_factory_{this};
};
#endif // IOS_CHROME_BROWSER_PRERENDER_MODEL_PRERENDER_BROWSER_AGENT_H_