// Copyright 2013 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_RENDERER_RENDER_FRAME_IMPL_H_ #define CONTENT_RENDERER_RENDER_FRAME_IMPL_H_ #include <stddef.h> #include <stdint.h> #include <map> #include <memory> #include <optional> #include <set> #include <string> #include <string_view> #include <unordered_set> #include <utility> #include <vector> #include "base/containers/id_map.h" #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/process/process_handle.h" #include "base/task/single_thread_task_runner.h" #include "base/timer/timer.h" #include "base/types/optional_ref.h" #include "base/unguessable_token.h" #include "base/uuid.h" #include "build/build_config.h" #include "cc/input/browser_controls_state.h" #include "content/common/buildflags.h" #include "content/common/content_export.h" #include "content/common/download/mhtml_file_writer.mojom.h" #include "content/common/frame.mojom.h" #include "content/common/navigation_client.mojom.h" #include "content/common/renderer.mojom.h" #include "content/common/web_ui.mojom.h" #include "content/public/common/alternative_error_page_override_info.mojom.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/extra_mojo_js_features.mojom.h" #include "content/public/common/referrer.h" #include "content/public/common/stop_find_action.h" #include "content/public/common/widget_type.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame_media_playback_options.h" #include "content/renderer/content_security_policy_util.h" #include "content/renderer/media/media_factory.h" #include "ipc/ipc_message.h" #include "ipc/ipc_platform_file.h" #include "media/base/routing_token_callback.h" #include "media/base/speech_recognition_client.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/system/data_pipe.h" #include "ppapi/buildflags/buildflags.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom-forward.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "third_party/blink/public/common/loader/loading_behavior_flag.h" #include "third_party/blink/public/common/permissions_policy/document_policy.h" #include "third_party/blink/public/common/permissions_policy/permissions_policy.h" #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h" #include "third_party/blink/public/common/subresource_load_metrics.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/common/unique_name/unique_name_helper.h" #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h" #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" #include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h" #include "third_party/blink/public/mojom/frame/frame_replication_state.mojom-forward.h" #include "third_party/blink/public/mojom/frame/policy_container.mojom-shared.h" #include "third_party/blink/public/mojom/frame/triggering_event_info.mojom-shared.h" #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-forward.h" #include "third_party/blink/public/mojom/loader/code_cache.mojom.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h" #include "third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom.h" #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h" #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h" #include "third_party/blink/public/mojom/render_accessibility.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom.h" #include "third_party/blink/public/platform/browser_interface_broker_proxy.h" #include "third_party/blink/public/platform/child_url_loader_factory_bundle.h" #include "third_party/blink/public/platform/web_media_player.h" #include "third_party/blink/public/platform/web_thread_safe_data.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/websocket_handshake_throttle_provider.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/public/web/web_frame_serializer.h" #include "third_party/blink/public/web/web_frame_serializer_client.h" #include "third_party/blink/public/web/web_history_commit_type.h" #include "third_party/blink/public/web/web_link_preview_triggerer.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_meaningful_layout.h" #include "ui/accessibility/ax_event.h" #include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/gfx/range/range.h" #include "url/gurl.h" #include "url/origin.h" #include "v8/include/v8-forward.h" #if BUILDFLAG(ENABLE_PPAPI) #include "content/common/pepper_plugin.mojom.h" #endif #if BUILDFLAG(IS_ANDROID) #include "content/common/gin_java_bridge.mojom.h" #endif namespace blink { namespace scheduler { class WebAgentGroupScheduler; } // namespace scheduler class WeakWrapperResourceLoadInfoNotifier; class WebBackgroundResourceFetchAssets; class WebContentDecryptionModule; class WebElement; class WebLocalFrame; class WebMediaStreamDeviceObserver; class WebString; class WebURL; struct FramePolicy; struct JavaScriptFrameworkDetectionResult; struct SoftNavigationMetrics; } // namespace blink namespace gfx { class Point; class Range; } // namespace gfx namespace media { class MediaPermission; } namespace url { class Origin; class SchemeHostPort; } // namespace url namespace content { class AgentSchedulingGroup; class BlinkInterfaceRegistryImpl; class DocumentState; class MediaPermissionDispatcher; class MHTMLPartsGenerationDelegateImpl; class NavigationClient; class PepperPluginInstanceImpl; class RendererPpapiHost; class RenderAccessibilityManager; class RenderFrameObserver; class CONTENT_EXPORT RenderFrameImpl : public RenderFrame, public blink::mojom::ResourceLoadInfoNotifier, blink::mojom::AutoplayConfigurationClient, public mojom::Frame, mojom::FrameBindingsControl, mojom::MhtmlFileWriter, public blink::WebLocalFrameClient, service_manager::mojom::InterfaceProvider { public: // Creates a new RenderFrame as the main frame of `web_view`. Note that not // all main RenderFrame creation uses this function. `CreateMainFrame()` // is used to create a RenderFrame that is immediately attached as the main // frame of the `web_view`. Meanwhile, `CreateFrame()` is used to create // provisional main RenderFrames (and subframe creation cases). static RenderFrameImpl* CreateMainFrame( AgentSchedulingGroup& agent_scheduling_group, blink::WebView* web_view, blink::WebFrame* opener, bool is_for_nested_main_frame, bool is_for_scalable_page, blink::mojom::FrameReplicationStatePtr replication_state, const base::UnguessableToken& devtools_frame_token, mojom::CreateLocalMainFrameParamsPtr params, const blink::WebURL& base_url); // Creates a new RenderFrame with |routing_id|. If |previous_frame_token| is // not provided, it creates the Blink WebLocalFrame and inserts it into // the frame tree after the frame identified by |previous_sibling_routing_id|, // or as the first child if |previous_sibling_routing_id| is MSG_ROUTING_NONE. // Otherwise, the frame is semi-orphaned until it commits, at which point it // replaces the previous object identified by |previous_frame_token|. The // previous object can either be a RenderFrame or a RenderFrameProxy. // The frame's opener is set to the frame identified by |opener_routing_id|. // The frame is created as a child of the RenderFrame identified by // |parent_routing_id| or as the top-level frame if // the latter is MSG_ROUTING_NONE. // |devtools_frame_token| is passed from the browser and corresponds to the // owner FrameTreeNode. It can only be used for tagging requests and calls // for context frame attribution. It should never be passed back to the // browser as a frame identifier in the control flows calls. // The |widget_params| is not null if the frame is to be a local root, which // means it will own a RenderWidget, in which case the |widget_params| hold // the routing id and initialization properties for the RenderWidget. // The |web_view| param will only be set when the frame to be created will use // new WebView, instead of using the previous Frame's WebView. This is only // possible for provisional main RenderFrames that will do a local main // RenderFrame swap later on with the frame that has the token // |previous_frame_token|. // // Note: This is called only when RenderFrame is being created in response // to IPC message from the browser process. All other frame creation is driven // through Blink and Create. static void CreateFrame( AgentSchedulingGroup& agent_scheduling_group, const blink::LocalFrameToken& token, int routing_id, mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver, mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker, mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider> associated_interface_provider, blink::WebView* web_view, base::optional_ref<const blink::FrameToken> previous_frame_token, base::optional_ref<const blink::FrameToken> opener_frame_token, base::optional_ref<const blink::FrameToken> parent_frame_token, base::optional_ref<const blink::FrameToken> previous_sibling_frame_token, const base::UnguessableToken& devtools_frame_token, blink::mojom::TreeScopeType tree_scope_type, blink::mojom::FrameReplicationStatePtr replicated_state, mojom::CreateFrameWidgetParamsPtr widget_params, blink::mojom::FrameOwnerPropertiesPtr frame_owner_properties, bool is_on_initial_empty_document, const blink::DocumentToken& document_token, blink::mojom::PolicyContainerPtr policy_container, bool is_for_nested_main_frame); #if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) // Returns the RenderFrameImpl for the given routing ID. static RenderFrameImpl* FromRoutingID(int routing_id); #endif // Just like RenderFrame::FromWebFrame but returns the implementation. static RenderFrameImpl* FromWebFrame(blink::WebFrame* web_frame); // Constructor parameters are bundled into a struct. struct CONTENT_EXPORT CreateParams { CreateParams( AgentSchedulingGroup& agent_scheduling_group, const blink::LocalFrameToken& frame_token, int32_t routing_id, mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver, mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider> associated_interface_provider, const base::UnguessableToken& devtools_frame_token, bool is_for_nested_main_frame); ~CreateParams(); CreateParams(CreateParams&&); CreateParams& operator=(CreateParams&&); raw_ptr<AgentSchedulingGroup> agent_scheduling_group; blink::LocalFrameToken frame_token; int32_t routing_id; mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver; mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider> associated_interface_provider; base::UnguessableToken devtools_frame_token; bool is_for_nested_main_frame; }; using CreateRenderFrameImplFunction = RenderFrameImpl* (*)(CreateParams); // Web tests override the creation of RenderFrames in order to inject a // partial testing fake. static void InstallCreateHook(CreateRenderFrameImplFunction create_frame); // Overwrites the given URL to use an HTML5 embed if possible. blink::WebURL OverrideFlashEmbedWithHTML(const blink::WebURL& url) override; RenderFrameImpl(const RenderFrameImpl&) = delete; RenderFrameImpl& operator=(const RenderFrameImpl&) = delete; ~RenderFrameImpl() override; // Returns the unique name of the RenderFrame. const std::string& unique_name() const { return unique_name_helper_.value(); } // Returns the blink::WebFrameWidget attached to the local root of this // frame. blink::WebFrameWidget* GetLocalRootWebFrameWidget(); // This method must be called after the WebLocalFrame backing this RenderFrame // has been created and added to the frame tree. It creates all objects that // depend on the frame being at its proper spot. // // Virtual for web tests to inject their own behaviour into the WebLocalFrame. virtual void Initialize(blink::WebFrame* parent); // Start/Stop loading notifications. // TODO(nasko): Those are page-level methods at this time and come from // WebViewClient. We should move them to be WebLocalFrameClient calls and put // logic in the browser side to balance starts/stops. void DidStartLoading() override; void DidStopLoading() override; // Returns the object implementing the RenderAccessibility mojo interface and // serves as a bridge between RenderFrameImpl and RenderAccessibilityImpl. RenderAccessibilityManager* GetRenderAccessibilityManager() { return render_accessibility_manager_.get(); } // Called from RenderAccessibilityManager to let the RenderFrame know when the // accessibility mode has changed, so that it can notify its observers. void NotifyAccessibilityModeChange(ui::AXMode new_mode); // Whether or not the frame is currently swapped into the frame tree. If // this is false, this is a provisional frame which has not committed yet, // and which will swap with a proxy when it commits. // // TODO(crbug.com/40452626): Remove this once provisional frames are // gone, and clean up code that depends on it. bool in_frame_tree() { return in_frame_tree_; } #if BUILDFLAG(ENABLE_PPAPI) mojom::PepperHost* GetPepperHost(); // Notification that a PPAPI plugin has been created. void PepperPluginCreated(RendererPpapiHost* host); // Informs the render view that a PPAPI plugin has changed text input status. void PepperTextInputTypeChanged(PepperPluginInstanceImpl* instance); void PepperCaretPositionChanged(PepperPluginInstanceImpl* instance); // Cancels current composition. void PepperCancelComposition(PepperPluginInstanceImpl* instance); // Informs the render view that a PPAPI plugin has changed selection. void PepperSelectionChanged(PepperPluginInstanceImpl* instance); #endif // BUILDFLAG(ENABLE_PPAPI) #if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) // IPC::Sender bool Send(IPC::Message* msg) override; // IPC::Listener bool OnMessageReceived(const IPC::Message& msg) override; #define LEGACY_IPC_OVERRIDE override #else #define LEGACY_IPC_OVERRIDE #endif void OnAssociatedInterfaceRequest(const std::string& interface_name, mojo::ScopedInterfaceEndpointHandle handle) LEGACY_IPC_OVERRIDE; #undef LEGACY_IPC_OVERRIDE // RenderFrame implementation: RenderFrame* GetMainRenderFrame() override; RenderAccessibility* GetRenderAccessibility() override; std::unique_ptr<AXTreeSnapshotter> CreateAXTreeSnapshotter( ui::AXMode ax_mode) override; #if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) int GetRoutingID() override; #endif blink::WebLocalFrame* GetWebFrame() override; const blink::WebLocalFrame* GetWebFrame() const override; blink::WebView* GetWebView() override; const blink::WebView* GetWebView() const override; const blink::web_pref::WebPreferences& GetBlinkPreferences() override; void ShowVirtualKeyboard() override; blink::WebPlugin* CreatePlugin(const WebPluginInfo& info, const blink::WebPluginParams& params) override; void ExecuteJavaScript(const std::u16string& javascript) override; bool IsMainFrame() override; bool IsInFencedFrameTree() const override; bool IsHidden() override; void BindLocalInterface( const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry() override; blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override; void SetSelectedText(const std::u16string& selection_text, size_t offset, const gfx::Range& range) override; void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level, const std::string& message) override; bool IsPasting() override; bool IsRequestingNavigation() override; void LoadHTMLStringForTesting(std::string_view html, const GURL& base_url, const std::string& text_encoding, const GURL& unreachable_url, bool replace_current_item) override; scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( blink::TaskType task_type) override; BindingsPolicySet GetEnabledBindings() override; void SetAccessibilityModeForTest(ui::AXMode new_mode) override; const RenderFrameMediaPlaybackOptions& GetRenderFrameMediaPlaybackOptions() override; void SetRenderFrameMediaPlaybackOptions( const RenderFrameMediaPlaybackOptions& opts) override; void SetAllowsCrossBrowsingInstanceFrameLookup() override; [[nodiscard]] gfx::Rect ConvertViewportToWindow( const gfx::Rect& rect) override; float GetDeviceScaleFactor() override; blink::scheduler::WebAgentGroupScheduler& GetAgentGroupScheduler() override; // blink::mojom::AutoplayConfigurationClient implementation: void AddAutoplayFlags(const url::Origin& origin, const int32_t flags) override; // blink::mojom::ResourceLoadInfoNotifier implementation: #if BUILDFLAG(IS_ANDROID) void NotifyUpdateUserGestureCarryoverInfo() override; #endif void NotifyResourceRedirectReceived( const net::RedirectInfo& redirect_info, network::mojom::URLResponseHeadPtr redirect_response) override; void NotifyResourceResponseReceived( int64_t request_id, const url::SchemeHostPort& final_response_url, network::mojom::URLResponseHeadPtr head, network::mojom::RequestDestination request_destination, bool is_ad_resource) override; void NotifyResourceTransferSizeUpdated(int64_t request_id, int32_t transfer_size_diff) override; void NotifyResourceLoadCompleted( blink::mojom::ResourceLoadInfoPtr resource_load_info, const ::network::URLLoaderCompletionStatus& status) override; void NotifyResourceLoadCanceled(int64_t request_id) override; void Clone(mojo::PendingReceiver<blink::mojom::ResourceLoadInfoNotifier> pending_resource_load_info_notifier) override; // mojom::FrameBindingsControl implementation: void AllowBindings(int64_t enabled_bindings_flags) override; void EnableMojoJsBindings( content::mojom::ExtraMojoJsFeaturesPtr features) override; void EnableMojoJsBindingsWithBroker( mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>) override; void BindWebUI( mojo::PendingAssociatedReceiver<mojom::WebUI> Receiver, mojo::PendingAssociatedRemote<mojom::WebUIHost> remote) override; // These mirror mojom::NavigationClient, called by NavigationClient. void CommitNavigation( blink::mojom::CommonNavigationParamsPtr common_params, blink::mojom::CommitNavigationParamsPtr commit_params, network::mojom::URLResponseHeadPtr response_head, mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories, std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>> subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> subresource_proxying_loader_factory, mojo::PendingRemote<network::mojom::URLLoaderFactory> keep_alive_loader_factory, mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory> fetch_later_loader_factory, const blink::DocumentToken& document_token, const base::UnguessableToken& devtools_navigation_token, const base::Uuid& base_auction_nonce, const std::optional<blink::ParsedPermissionsPolicy>& permissions_policy, blink::mojom::PolicyContainerPtr policy_container, mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host, mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host_for_background, mojom::CookieManagerInfoPtr cookie_manager_info, mojom::StorageInfoPtr storage_info, mojom::NavigationClient::CommitNavigationCallback commit_callback); void CommitFailedNavigation( blink::mojom::CommonNavigationParamsPtr common_params, blink::mojom::CommitNavigationParamsPtr commit_params, bool has_stale_copy_in_cache, int error_code, int extended_error_code, net::ResolveErrorInfo resolve_error_info, const std::optional<std::string>& error_page_content, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories, const blink::DocumentToken& document_token, blink::mojom::PolicyContainerPtr policy_container, mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info, mojom::NavigationClient::CommitFailedNavigationCallback per_navigation_mojo_interface_callback); // mojom::MhtmlFileWriter implementation: void SerializeAsMHTML(const mojom::SerializeAsMHTMLParamsPtr params, SerializeAsMHTMLCallback callback) override; // blink::WebLocalFrameClient implementation: void BindToFrame(blink::WebNavigationControl* frame) override; blink::WebPlugin* CreatePlugin(const blink::WebPluginParams& params) override; std::unique_ptr<blink::WebMediaPlayer> CreateMediaPlayer( const blink::WebMediaPlayerSource& source, blink::WebMediaPlayerClient* client, blink::MediaInspectorContext* inspector_context, blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, blink::WebContentDecryptionModule* initial_cdm, const blink::WebString& sink_id, const cc::LayerTreeSettings* settings, scoped_refptr<base::TaskRunner> compositor_worker_task_runner) override; std::unique_ptr<blink::WebContentSettingsClient> CreateWorkerContentSettingsClient() override; #if !BUILDFLAG(IS_ANDROID) std::unique_ptr<media::SpeechRecognitionClient> CreateSpeechRecognitionClient() override; #endif scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext() override; scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContextForPlzDedicatedWorker( blink::WebDedicatedWorkerHostFactoryClient* factory_client) override; std::unique_ptr<blink::WebPrescientNetworking> CreatePrescientNetworking() override; std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper> CreateResourceLoadInfoNotifierWrapper() override; std::unique_ptr<blink::WebServiceWorkerProvider> CreateServiceWorkerProvider() override; blink::AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces() override; blink::WebLocalFrame* CreateChildFrame( blink::mojom::TreeScopeType scope, const blink::WebString& name, const blink::WebString& fallback_name, const blink::FramePolicy& frame_policy, const blink::WebFrameOwnerProperties& frame_owner_properties, blink::FrameOwnerElementType frame_owner_element_type, blink::WebPolicyContainerBindParams policy_container_bind_params, ukm::SourceId document_ukm_source_id, FinishChildFrameCreationFn finish_creation) override; void DidCreateFencedFrame( const blink::RemoteFrameToken& frame_token) override; blink::WebFrame* FindFrame(const blink::WebString& name) override; void WillDetach(blink::DetachReason detach_reason) override; void FrameDetached(blink::DetachReason detach_reason) override; void DidChangeName(const blink::WebString& name) override; void DidMatchCSS( const blink::WebVector<blink::WebString>& newly_matching_selectors, const blink::WebVector<blink::WebString>& stopped_matching_selectors) override; bool ShouldReportDetailedMessageForSourceAndSeverity( blink::mojom::ConsoleMessageLevel log_level, const blink::WebString& source) override; void DidAddMessageToConsole(const blink::WebConsoleMessage& message, const blink::WebString& source_name, unsigned source_line, const blink::WebString& stack_trace) override; void BeginNavigation(std::unique_ptr<blink::WebNavigationInfo> info) override; void DidCreateDocumentLoader( blink::WebDocumentLoader* document_loader) override; bool SwapIn(blink::WebFrame* previous_web_frame) override; void DidCommitNavigation( blink::WebHistoryCommitType commit_type, bool should_reset_browser_interface_broker, const blink::ParsedPermissionsPolicy& permissions_policy_header, const blink::DocumentPolicyFeatureState& document_policy_header) override; void DidCommitDocumentReplacementNavigation( blink::WebDocumentLoader* document_loader) override; void DidClearWindowObject() override; void DidCreateDocumentElement() override; void RunScriptsAtDocumentElementAvailable() override; void DidReceiveTitle(const blink::WebString& title) override; void DidDispatchDOMContentLoadedEvent() override; void RunScriptsAtDocumentReady() override; void RunScriptsAtDocumentIdle() override; void DidHandleOnloadEvents() override; void DidFinishLoad() override; void DidFinishLoadForPrinting() override; void DidFinishSameDocumentNavigation( blink::WebHistoryCommitType commit_type, bool is_synchronously_committed, blink::mojom::SameDocumentNavigationType same_document_navigation_type, bool is_client_redirect, const std::optional<blink::SameDocNavigationScreenshotDestinationToken>& screenshot_destination) override; void DidFailAsyncSameDocumentCommit() override; void WillFreezePage() override; void DidOpenDocumentInputStream(const blink::WebURL& url) override; void DidSetPageLifecycleState(bool restoring_from_bfcache) override; void NotifyCurrentHistoryItemChanged() override; void DidUpdateCurrentHistoryItem() override; base::UnguessableToken GetDevToolsFrameToken() override; void AbortClientNavigation(bool for_new_navigation) override; void DidChangeSelection(bool is_empty_selection, blink::SyncCondition force_sync) override; void FocusedElementChanged(const blink::WebElement& element) override; void OnMainFrameIntersectionChanged( const gfx::Rect& main_frame_intersection_rect) override; void OnMainFrameViewportRectangleChanged( const gfx::Rect& main_frame_viewport_rect) override; void OnMainFrameImageAdRectangleChanged( int element_id, const gfx::Rect& image_ad_rect) override; void FinalizeRequest(blink::WebURLRequest& request) override; std::optional<blink::WebURL> WillSendRequest( const blink::WebURL& target, const blink::WebSecurityOrigin& security_origin, const net::SiteForCookies& site_for_cookies, ForRedirect for_redirect, const blink::WebURL& upstream_url) override; void OnOverlayPopupAdDetected() override; void OnLargeStickyAdDetected() override; void DidLoadResourceFromMemoryCache( const blink::WebURLRequest& request, const blink::WebURLResponse& response) override; void DidChangePerformanceTiming() override; void DidObserveUserInteraction(base::TimeTicks max_event_start, base::TimeTicks max_event_queued_main_thread, base::TimeTicks max_event_commit_finish, base::TimeTicks max_event_end, uint64_t interaction_offset) override; void DidChangeCpuTiming(base::TimeDelta time) override; void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override; void DidObserveJavaScriptFrameworks( const blink::JavaScriptFrameworkDetectionResult&) override; void DidObserveSubresourceLoad( const blink::SubresourceLoadMetrics& subresource_load_metrics) override; void DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) override; void DidObserveSoftNavigation(blink::SoftNavigationMetrics metrics) override; void DidObserveLayoutShift(double score, bool after_input_or_scroll) override; void DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) override; void WillReleaseScriptContext(v8::Local<v8::Context> context, int world_id) override; void DidChangeScrollOffset() override; blink::WebMediaStreamDeviceObserver* MediaStreamDeviceObserver() override; blink::WebEncryptedMediaClient* EncryptedMediaClient() override; blink::WebString UserAgentOverride() override; std::optional<blink::UserAgentMetadata> UserAgentMetadataOverride() override; blink::mojom::RendererAudioInputStreamFactory* GetAudioInputStreamFactory(); bool AllowContentInitiatedDataUrlNavigations( const blink::WebURL& url) override; void PostAccessibilityEvent(const ui::AXEvent& event) override; bool SendAccessibilitySerialization( std::vector<ui::AXTreeUpdate> updates, std::vector<ui::AXEvent> events, ui::AXLocationAndScrollUpdates location_and_scroll_updates, bool had_load_complete_messages) override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; blink::URLLoaderThrottleProvider* GetURLLoaderThrottleProvider() override; scoped_refptr<blink::WebBackgroundResourceFetchAssets> MaybeGetBackgroundResourceFetchAssets() override; void OnStopLoading() override; const blink::BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() override; blink::WebView* CreateNewWindow( const blink::WebURLRequest& request, const blink::WebWindowFeatures& features, const blink::WebString& frame_name, blink::WebNavigationPolicy policy, network::mojom::WebSandboxFlags sandbox_flags, const blink::SessionStorageNamespaceId& session_storage_namespace_id, bool& consumed_user_gesture, const std::optional<blink::Impression>& impression, const std::optional<blink::WebPictureInPictureWindowOptions>& pip_options, const blink::WebURL& base_url) override; std::unique_ptr<blink::WebLinkPreviewTriggerer> CreateLinkPreviewTriggerer() override; // Dispatches the current state of selection on the webpage to the browser if // it has changed or if the forced flag is passed. The forced flag is used // when the browser selection may be out of sync with the renderer due to // incorrect prediction. void SyncSelectionIfRequired(blink::SyncCondition force_sync) override; void CreateAudioInputStream( blink::CrossVariantMojoRemote< blink::mojom::RendererAudioInputStreamFactoryClientInterfaceBase> client, const base::UnguessableToken& session_id, const media::AudioParameters& params, bool automatic_gain_control, uint32_t shared_memory_count, blink::CrossVariantMojoReceiver< media::mojom::AudioProcessorControlsInterfaceBase> controls_receiver, const media::AudioProcessingSettings* settings) override; void AssociateInputAndOutputForAec( const base::UnguessableToken& input_stream_id, const std::string& output_device_id) override; void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) override; void DidCommitAndDrawCompositorFrame() override; void WasHidden() override; void WasShown() override; void OnFrameVisibilityChanged( blink::mojom::FrameVisibility render_status) override; void SetUpSharedMemoryForSmoothness( base::ReadOnlySharedMemoryRegion shared_memory) override; blink::WebURL LastCommittedUrlForUKM() override; void ScriptedPrint() override; // Possibly defers the loading of media resources. // // This function defers in two cases: // - In the normal case, it calls ContentRendererClient::DeferMediaLoad() // to give the embedder a chance to defer. // - If the frame is prerendering, this function defers the load. It // calls ContentRendererClient::DeferMediaLoad() once activation // occurs. // // `closure` is run when loading should proceed. Returns true if running // of |closure| is deferred; false if run immediately. // // If `has_played_media_before` is true, the render frame has previously // started media playback (i.e. played audio and video). bool DeferMediaLoad(bool has_played_media_before, base::OnceClosure closure); // Binds to the MHTML file generation service in the browser. void BindMhtmlFileWriter( mojo::PendingAssociatedReceiver<mojom::MhtmlFileWriter> receiver); #if BUILDFLAG(IS_ANDROID) void BindGinJavaBridge( mojo::PendingAssociatedReceiver<mojom::GinJavaBridge> receiver); #endif // Binds to the autoplay configuration service in the browser. void BindAutoplayConfiguration( mojo::PendingAssociatedReceiver<blink::mojom::AutoplayConfigurationClient> receiver); void BindFrameBindingsControl( mojo::PendingAssociatedReceiver<mojom::FrameBindingsControl> receiver); void BindNavigationClient( mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver); void BindNavigationClientWithParams( mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver, blink::mojom::BeginNavigationParamsPtr begin_params, blink::mojom::CommonNavigationParamsPtr common_params, bool is_duplicate_navigation); // Virtual so that a TestRenderFrame can mock out the interface. virtual mojom::FrameHost* GetFrameHost(); media::MediaPermission* GetMediaPermission(); // Sends the current frame's navigation state to the browser. void SendUpdateState(); // Creates a MojoBindingsController if Mojo bindings have been enabled for // this frame. For WebUI, this allows the page to communicate with the browser // process; for layout tests, this allows the test to mock out services at // the Mojo IPC layer. void MaybeEnableMojoBindings(); void NotifyObserversOfFailedProvisionalLoad(); // Plugin-related functions -------------------------------------------------- #if BUILDFLAG(ENABLE_PPAPI) PepperPluginInstanceImpl* focused_pepper_plugin() { return focused_pepper_plugin_; } // Indicates that the given instance has been created. void PepperInstanceCreated( PepperPluginInstanceImpl* instance, mojo::PendingAssociatedRemote<mojom::PepperPluginInstance> mojo_instance, mojo::PendingAssociatedReceiver<mojom::PepperPluginInstanceHost> mojo_host); // Indicates that the given instance is being destroyed. This is called from // the destructor, so it's important that the instance is not dereferenced // from this call. void PepperInstanceDeleted(PepperPluginInstanceImpl* instance); // Notification that the given plugin is focused or unfocused. void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused); void OnSetPepperVolume(int32_t pp_instance, double volume); #endif // BUILDFLAG(ENABLE_PPAPI) const blink::RendererPreferences& GetRendererPreferences() const; // Called when an ongoing renderer-initiated navigation was dropped by the // browser. void OnDroppedNavigation(); void DidStartResponse(const url::SchemeHostPort& final_response_url, int request_id, network::mojom::URLResponseHeadPtr response_head, network::mojom::RequestDestination request_destination, bool is_ad_resource); void DidCompleteResponse(int request_id, const network::URLLoaderCompletionStatus& status); void DidCancelResponse(int request_id); void DidReceiveTransferSizeUpdate(int request_id, int received_data_length); bool GetCaretBoundsFromFocusedPlugin(gfx::Rect& rect) override; // Used in tests to install a fake URLLoaderFactory via // RenderViewTest::CreateFakeURLLoaderFactory(). void SetURLLoaderFactoryOverrideForTest( scoped_refptr<network::SharedURLLoaderFactory> factory); // Clones and returns `this` frame's blink::ChildURLLoaderFactoryBundle. scoped_refptr<blink::ChildURLLoaderFactoryBundle> CloneLoaderFactories(); url::Origin GetSecurityOriginOfTopFrame(); void set_send_content_state_immediately(bool value) { send_content_state_immediately_ = value; } base::WeakPtr<media::DecoderFactory> GetMediaDecoderFactory(); // Returns a blink::ChildURLLoaderFactoryBundle which can be used to request // subresources for this frame. // // The returned bundle was typically sent by the browser process when // committing a navigation, but in some cases (about:srcdoc, initial empty // document) it may be inherited from the parent or opener. blink::ChildURLLoaderFactoryBundle* GetLoaderFactoryBundle() override; protected: explicit RenderFrameImpl(CreateParams params); bool IsLocalRoot() const; const RenderFrameImpl* GetLocalRoot() const; base::WeakPtr<RenderFrameImpl> GetWeakPtr(); private: friend class RenderFrameImplTest; friend class RenderFrameObserver; friend class TestRenderFrame; FRIEND_TEST_ALL_PREFIXES(RenderAccessibilityImplTest, AccessibilityMessagesQueueWhileSwappedOut); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest, LocalChildFrameWasShown); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest, ZoomLimit); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest, TestOverlayRoutingTokenSendsLater); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest, TestOverlayRoutingTokenSendsNow); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest, SendUpdateCancelsPending); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplMojoJsDeathTest, EnabledBindingsTampered); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplMojoJsDeathTest, EnableMojoJsBindingsTampered); FRIEND_TEST_ALL_PREFIXES(RenderFrameImplMojoJsDeathTest, MojoJsInterfaceBrokerTampered); // Similar to base::AutoReset, but skips restoration of the original value if // |this| is already destroyed. template <typename T> class AutoResetMember { public: AutoResetMember(RenderFrameImpl* frame, T RenderFrameImpl::*member, T new_value) : weak_frame_(frame->weak_factory_.GetWeakPtr()), scoped_variable_(&(frame->*member)), original_value_(*scoped_variable_) { *scoped_variable_ = new_value; } ~AutoResetMember() { if (weak_frame_) *scoped_variable_ = original_value_; } private: base::WeakPtr<RenderFrameImpl> weak_frame_; raw_ptr<T> scoped_variable_; T original_value_; }; // Creates a new RenderFrame. static RenderFrameImpl* Create( AgentSchedulingGroup& agent_scheduling_group, const blink::LocalFrameToken& frame_token, int32_t routing_id, mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver, mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider> associated_interface_provider, const base::UnguessableToken& devtools_frame_token, bool is_for_nested_main_frame); // Functions to add and remove observers for this object. void AddObserver(RenderFrameObserver* observer); void RemoveObserver(RenderFrameObserver* observer); // Checks whether accessibility support for this frame is currently enabled. bool IsAccessibilityEnabled() const override; // mojom::Frame implementation: void CommitSameDocumentNavigation( blink::mojom::CommonNavigationParamsPtr common_params, blink::mojom::CommitNavigationParamsPtr commit_params, CommitSameDocumentNavigationCallback callback) override; void UpdateSubresourceLoaderFactories( std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories) override; void SetWantErrorMessageStackTrace() override; void Unload( bool is_loading, blink::mojom::FrameReplicationStatePtr replicated_frame_state, const blink::RemoteFrameToken& frame_token, blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces, blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces, const std::optional<base::UnguessableToken>& devtools_frame_token) override; void Delete(mojom::FrameDeleteIntention intent) override; void UndoCommitNavigation( bool is_loading, blink::mojom::FrameReplicationStatePtr replicated_frame_state, const blink::RemoteFrameToken& frame_token, blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces, blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) override; void GetInterfaceProvider( mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver) override; void SnapshotAccessibilityTree( mojom::SnapshotAccessibilityTreeParamsPtr params, SnapshotAccessibilityTreeCallback callback) override; void GetSerializedHtmlWithLocalLinks( const base::flat_map<GURL, base::FilePath>& url_map, const base::flat_map<blink::FrameToken, base::FilePath>& frame_token_map, bool save_with_empty_url, mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote) override; void OnSerializeMHTMLComplete( std::unique_ptr<MHTMLPartsGenerationDelegateImpl> delegate, SerializeAsMHTMLCallback callback, std::vector<blink::WebThreadSafeData> mhtml_contents, blink::WebThreadSafeData frame_mhtml_data); // Callback scheduled from SerializeAsMHTML for when writing serialized // MHTML to the handle has been completed in the file thread. void OnWriteMHTMLComplete( SerializeAsMHTMLCallback callback, std::unordered_set<std::string> serialized_resources_uri_digests, mojom::MhtmlSaveStatus save_status); // Requests that the browser process navigates to |url|. void OpenURL(std::unique_ptr<blink::WebNavigationInfo> info); // Sets `loader_factories_`. And clears `background_resource_fetch_context_`. // `background_resource_fetch_context_` will be lazily initialized when // creating a WebURLLoader if BackgroundResourceFetch feature is enabled. void SetLoaderFactoryBundle( scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories); scoped_refptr<blink::ChildURLLoaderFactoryBundle> CreateLoaderFactoryBundle( std::unique_ptr<blink::PendingURLLoaderFactoryBundle> info, std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>> subresource_overrides, mojo::PendingRemote<network::mojom::URLLoaderFactory> subresource_proxying_loader_factory, mojo::PendingRemote<network::mojom::URLLoaderFactory> keep_alive_loader_factory, mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory> fetch_later_loader_factory); // Update current main frame's encoding and send it to browser window. // Since we want to let users see the right encoding info from menu // before finishing loading, we call the UpdateEncoding in // a) function:DidCommitLoadForFrame. When this function is called, // that means we have got first data. In here we try to get encoding // of page if it has been specified in http header. // b) function:DidReceiveTitle. When this function is called, // that means we have got specified title. Because in most of webpages, // title tags will follow meta tags. In here we try to get encoding of // page if it has been specified in meta tag. // c) function:DidDispatchDOMContentLoadedEvent. When this function is // called, that means we have got whole html page. In here we should // finally get right encoding of page. void UpdateEncoding(blink::WebFrame* frame, const std::string& encoding_name); void InitializeMediaStreamDeviceObserver(); // Called when the RenderFrameImpl is created. This either: // - creates and initializes the WebFrameWidget with a new compositor, i.e. // the "typical" case or // - stashes the creation params for later use. Experimental mode used only // for local -> local RenderFrame swaps. Widget creation will be deferred // until commit; when created, the widget will reuse the previous // RenderFrame's compositor. void MaybeInitializeWidget(mojom::CreateFrameWidgetParamsPtr widget_params); // Called during a LocalFrame<->LocalFrame swap. This creates and initializes // the WebFrameWidget if it was deferred when the RenderFrameImpl was created, // see `MaybeInitializeWidget()` above. void InitializeWidgetAtSwap(blink::WebLocalFrame& previous_frame); // Sends a FrameHostMsg_BeginNavigation to the browser void BeginNavigationInternal(std::unique_ptr<blink::WebNavigationInfo> info, bool is_history_navigation_in_new_child_frame, base::TimeTicks renderer_before_unload_start, base::TimeTicks renderer_before_unload_end); // TODO(crbug.com/40546539): When creating a new browsing context, Blink // always populates it with an initial empty document synchronously, as // required by the HTML spec. However, for both iframe and window creation, // there is an additional special case that currently requires completing an // about:blank navigation synchronously. // // 1. Inserting an <iframe> into the active document with no src and no // srcdoc or with src = "about:blank". // 2. Opening a new window with no specified URL or with URL = "about:blank". // // In both cases, Blink will initialize the new browsing context, and then // immediately re-navigate to "about:blank". This leads to a number of odd // situations throughout the navigation stack, and it is spec-incompliant. // // For a new <iframe>, the re-navigation to "about:blank" should be a regular // asynchronous navigation. // // For a new window, there should be no navigation at all: the standard states // that a load event should be dispatched, and nothing else. // // See also: // - https://chromium-review.googlesource.com/c/chromium/src/+/804797 // - https://github.com/whatwg/html/issues/3267 void SynchronouslyCommitAboutBlankForBug778318( std::unique_ptr<blink::WebNavigationInfo> info); // Commit navigation with |navigation_params| prepared. void CommitNavigationWithParams( blink::mojom::CommonNavigationParamsPtr common_params, blink::mojom::CommitNavigationParamsPtr commit_params, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories, std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>> subresource_overrides, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, mojo::PendingRemote<network::mojom::URLLoaderFactory> subresource_proxying_loader_factory, mojo::PendingRemote<network::mojom::URLLoaderFactory> keep_alive_loader_factory, mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory> fetch_later_loader_factory, mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host, mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host_for_background, mojom::CookieManagerInfoPtr cookie_manager_info, mojom::StorageInfoPtr storage_info, std::unique_ptr<DocumentState> document_state, std::unique_ptr<blink::WebNavigationParams> navigation_params); // Decodes a data url for navigation commit. void DecodeDataURL(const blink::mojom::CommonNavigationParams& common_params, const blink::mojom::CommitNavigationParams& commit_params, std::string* mime_type, std::string* charset, std::string* data, GURL* base_url); void FinalizeRequestInternal(blink::WebURLRequest& request, bool for_outermost_main_frame, ui::PageTransition transition_type); // |transition_type| corresponds to the document which triggered this request. std::optional<blink::WebURL> WillSendRequestInternal( const blink::WebURL& target, const blink::WebSecurityOrigin& security_origin, const net::SiteForCookies& site_for_cookies, ForRedirect for_redirect, const blink::WebURL& upstream_url, ui::PageTransition transition_type); // Returns the URL being loaded by the |frame_|'s request. GURL GetLoadingUrl() const; void RegisterMojoInterfaces(); // service_manager::mojom::InterfaceProvider: void GetInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; // Send |callback| our AndroidOverlay routing token. void RequestOverlayRoutingToken(media::RoutingTokenCallback callback); void BindWebUIReceiver(mojo::PendingReceiver<mojom::WebUI> receiver); // Build DidCommitProvisionalLoadParams based on the frame internal state. mojom::DidCommitProvisionalLoadParamsPtr MakeDidCommitProvisionalLoadParams( blink::WebHistoryCommitType commit_type, ui::PageTransition transition, const blink::ParsedPermissionsPolicy& permissions_policy_header, const blink::DocumentPolicyFeatureState& document_policy_header, const std::optional<base::UnguessableToken>& embedding_token); // Updates the navigation history depending on the passed parameters. // This could result either in the creation of a new entry or a modification // of the current entry or nothing. If a new entry was created, // returns true, false otherwise. void UpdateNavigationHistory(blink::WebHistoryCommitType commit_type); // Notify render_view_ observers that a commit happened. void NotifyObserversOfNavigationCommit(ui::PageTransition transition); // Updates the internal state following a navigation commit. This should be // called before notifying the FrameHost of the commit. void UpdateStateForCommit(blink::WebHistoryCommitType commit_type, ui::PageTransition transition); // Internal function used by same document navigation as well as cross // document navigation that updates the state of the RenderFrameImpl and sends // a commit message to the browser process. void DidCommitNavigationInternal( blink::WebHistoryCommitType commit_type, ui::PageTransition transition, const blink::ParsedPermissionsPolicy& permissions_policy_header, const blink::DocumentPolicyFeatureState& document_policy_header, mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params, mojom::DidCommitSameDocumentNavigationParamsPtr same_document_params, const std::optional<base::UnguessableToken>& embedding_token); std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle() override; bool IsPluginHandledExternally( const blink::WebElement& plugin_element, const blink::WebURL& url, const blink::WebString& suggested_mime_type) override; bool IsDomStorageDisabled() const override; v8::Local<v8::Object> GetScriptableObject( const blink::WebElement& plugin_element, v8::Isolate* isolate) override; // Updates the state of this frame when asked to commit a navigation. void PrepareFrameForCommit( const GURL& url, const blink::mojom::CommitNavigationParams& commit_params); // Returns true if UA (and UA client hints) overrides in renderer preferences // should be used. bool ShouldUseUserAgentOverride() const; // Sets the PageLifecycleState and runs pagehide and visibilitychange handlers // of the old page before committing this RenderFrame. Should only be called // for main-frame same-site navigations where we did a proactive // BrowsingInstance swap and we're reusing the old page's process. This is // needed to ensure consistency with other same-site main frame navigations. // Note that we will set the page's visibility to hidden, but not run the // unload handlers of the old page, nor actually unload/freeze the page here. // That needs a more complicated support on the browser side which will be // implemented later. // TODO(crbug.com/40142288): Support unload-in-commit. void SetOldPageLifecycleStateFromNewPageCommitIfNeeded( const blink::mojom::OldPageInfo* old_page_info, const GURL& new_page_url); // Updates the state when asked to commit a history navigation. Sets // |item_for_history_navigation| and |load_type| to the appropriate values for // commit. // // The function will also return whether to proceed with the commit of a // history navigation or not. This can return false when the state of the // history in the browser process goes out of sync with the renderer process. // This can happen in the following scenario: // * this RenderFrame has a document with URL foo, which does a push state // to foo#bar. // * the user starts a navigation to foo/bar. // * the browser process asks this renderer process to commit the navigation // to foo/bar. // * the browser process starts a navigation back to foo, which it // considers same-document since the navigation to foo/bar hasn't // committed yet. It asks the RenderFrame to commit the same-document // navigation to foo#bar. // * by the time the RenderFrame receives the call to commit the // same-document back navigation, the navigation to foo/bar has committed. // A back navigation to foo is no longer same-document with the current // document of the RenderFrame (foo/bar). Therefore, the navigation cannot // be committed as a same-document navigation. // When this happens, the navigation will be sent back to the browser process // so that it can be performed in cross-document fashion. blink::mojom::CommitResult PrepareForHistoryNavigationCommit( const blink::mojom::CommonNavigationParams& common_params, const blink::mojom::CommitNavigationParams& commit_params, blink::WebHistoryItem* item_for_history_navigation, blink::WebFrameLoadType* load_type); // Implements AddMessageToConsole(). void AddMessageToConsoleImpl(blink::mojom::ConsoleMessageLevel level, const std::string& message, bool discard_duplicates); // Start a delayed timer to update the frame sync state to the browser. // Debounces many updates in quick succession. void StartDelayedSyncTimer(); // Swaps out the RenderFrame, creating a new `blink::RemoteFrame` and then // swapping it into the frame tree to replace `this`. Returns false if // swapping out `this` ends up detaching this frame instead when running the // unload handlers, and true otherwise. // // Important: after this method returns, `this` has been deleted. bool SwapOutAndDeleteThis( bool is_loading, blink::mojom::FrameReplicationStatePtr replicated_frame_state, const blink::RemoteFrameToken& frame_token, blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces, blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces, const std::optional<base::UnguessableToken>& devtools_frame_token); // Resets membmers that are needed for the duration of commit (time between // CommitNavigation() and DidCommitNavigation(). void ResetMembersUsedForDurationOfCommit(); // Stores the WebLocalFrame we are associated with. This is null from the // constructor until BindToFrame() is called, and it is null after // FrameDetached() is called until destruction (which is asynchronous in the // case of the main frame, but not subframes). raw_ptr<blink::WebNavigationControl> frame_ = nullptr; // The `AgentSchedulingGroup` this frame is associated with. const raw_ref<AgentSchedulingGroup> agent_scheduling_group_; // False until Initialize() is run, to avoid actions before the frame's // observers are created. bool initialized_ = false; // Boolean value indicating whether this RenderFrameImpl object is for the // main frame or not. It remains accurate during destruction, even when // |frame_| has been invalidated. bool is_main_frame_; class UniqueNameFrameAdapter : public blink::UniqueNameHelper::FrameAdapter { public: explicit UniqueNameFrameAdapter(RenderFrameImpl* render_frame); ~UniqueNameFrameAdapter() override; // FrameAdapter overrides: bool IsMainFrame() const override; bool IsCandidateUnique(std::string_view name) const override; int GetSiblingCount() const override; int GetChildCount() const override; std::vector<std::string> CollectAncestorNames( BeginPoint begin_point, bool (*should_stop)(std::string_view)) const override; std::vector<int> GetFramePosition(BeginPoint begin_point) const override; private: blink::WebLocalFrame* GetWebFrame() const; raw_ptr<RenderFrameImpl> render_frame_; }; UniqueNameFrameAdapter unique_name_frame_adapter_; blink::UniqueNameHelper unique_name_helper_; // Indicates whether the frame has been inserted into the frame tree yet or // not. // // When a frame is created by the browser process, it is for a pending // navigation. In this case, it is not immediately attached to the frame tree // if there is a `blink::RemoteFrame` for the same frame. It is inserted into // the frame tree at the time the pending navigation commits. Frames added by // the parent document are created from the renderer process and are // immediately inserted in the frame tree. // TODO(dcheng): Remove this once we have FrameTreeHandle and can use the // Blink Web* layer to check for provisional frames. bool in_frame_tree_; blink::LocalFrameToken frame_token_; #if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) const int routing_id_; #endif const int process_label_id_; // Keeps track of which future subframes the browser process has history items // for during a history navigation, as well as whether those items are for // about:blank. The renderer process should ask the browser for history items // when subframes with these names are created (as long as they are not // staying at about:blank), and directly load the initial URLs for any other // subframes. // // This state is incrementally cleared as it is used and then reset in // didStopLoading, since it is not needed after the first load completes and // is never used after the initial navigation. // TODO(creis): Expand this to include any corresponding same-process // PageStates for the whole subtree in https://crbug.com/639842. base::flat_map<std::string, bool> history_subframe_unique_names_; // All the registered observers. base::ObserverList<RenderFrameObserver>::Unchecked observers_; // The text selection the last time DidChangeSelection got called. May contain // additional characters before and after the selected text, for IMEs. The // portion of this string that is the actual selected text starts at index // |selection_range_.GetMin() - selection_text_offset_| and has length // |selection_range_.length()|. std::u16string selection_text_; // The offset corresponding to the start of |selection_text_| in the document. size_t selection_text_offset_; // Range over the document corresponding to the actual selected text (which // could correspond to a substring of |selection_text_|; see above). gfx::Range selection_range_; // Implements getUserMedia() and related functionality. std::unique_ptr<blink::WebMediaStreamDeviceObserver> web_media_stream_device_observer_; mojo::Remote<blink::mojom::RendererAudioInputStreamFactory> audio_input_stream_factory_; // This interface handles generated code cache requests both to fetch code // cache when loading resources and to store code caches when code caches are // generated during the JS / Wasm script execution. mojo::Remote<blink::mojom::CodeCacheHost> code_cache_host_; // The media permission dispatcher attached to this frame. std::unique_ptr<MediaPermissionDispatcher> media_permission_dispatcher_; service_manager::BinderRegistry registry_; std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_; // If valid, the next ExecutionContext created will enable MojoJS bindings and // use this broker to handle Mojo.bindInterface calls. mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> mojo_js_interface_broker_; // Valid during the entire life time of the RenderFrame. std::unique_ptr<RenderAccessibilityManager> render_accessibility_manager_; std::unique_ptr<blink::WeakWrapperResourceLoadInfoNotifier> weak_wrapper_resource_load_info_notifier_; // Plugins ------------------------------------------------------------------- #if BUILDFLAG(ENABLE_PPAPI) typedef std::set<raw_ptr<PepperPluginInstanceImpl, SetExperimental>> PepperPluginSet; PepperPluginSet active_pepper_instances_; // Whether or not the focus is on a PPAPI plugin raw_ptr<PepperPluginInstanceImpl> focused_pepper_plugin_; mojo::AssociatedRemote<mojom::PepperHost> pepper_host_remote_; #endif using AutoplayOriginAndFlags = std::pair<url::Origin, int32_t>; AutoplayOriginAndFlags autoplay_flags_; mojo::AssociatedReceiver<blink::mojom::AutoplayConfigurationClient> autoplay_configuration_receiver_{this}; // The mojom::Frame can not be bound at construction because it needs the // WebFrame to get a TaskRunner from so it is stashed here. mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver_; mojo::AssociatedReceiver<mojom::Frame> frame_receiver_{this}; mojo::AssociatedReceiver<mojom::FrameBindingsControl> frame_bindings_control_receiver_{this}; mojo::AssociatedReceiver<mojom::MhtmlFileWriter> mhtml_file_writer_receiver_{ this}; // There are two different kinds of NavigationClients, the request // NavigationClient and the commit NavigationClient. // // ## Request NavigationClient ## // Set if and only if the frame that initiated the navigation and the frame // being navigated are both RenderFrameImpls in the same frame tree (i.e. the // navigation does not ever go through a RenderFrameProxy). This has // interesting implications for behavior differences between the two example // frame trees below: // // a.com a.com // ↓ ↓ // b.com example.a.com // // Assuming the standard site-per-process allocation policy, though (a.com) is // cross-origin to both (b.com) and (example.a.com): // // - (a.com) performing a navigation in (b.com) *will not* create a request // NavigationClient but // - (a.com) performing a navigation in (example.a.com) *will* create a // request NavigationClient // // Note that the initiating RenderFrameImpl does *not* own the request // NavigationClient. Rather, the RenderFrameImpl that the navigation *targets* // is the RenderFrameImpl that owns the request NavigationClient. // // ## Commit NavigationClient ## // Always set in the RenderFrameImpl that has been selected to commit a // navigation. This selection happens when the NavigationRequest in the // browser process reaches READY_TO_COMMIT. // // If a navigation will commit in the same RenderFrameImpl that owns the // request NavigationClient, the request NavigationClient will be reused as // the commit NavigationClient. The way this works is: // 1.) RenderFrameHostImpl::BeginNavigation() accepts an always-bound remote // to the RenderFrameImpl's `navigation_client_impl_`. // 2.) In `NavigationRequest::ctor()`, the request consumes the // NavigationClient remote, and // `NavigationRequest::SetNavigationClient()` assigns // `NavigationRequest::request_navigation_client_` to it. // 3.) Eventually, `NavigationRequest` picks a `RenderFrameHostImpl` to // commit // to. In `NavigationRequest::CommitNavigation()`, the request needs to // set its `commit_navigation_client_` to the `NavigationClient` // implementation in the target RenderFrameImpl. If we detect that the // navigation will commit to the same frame that // `NavigationRequest::request_navigation_client_` points to, then the // browser will reuse the request navigation client as the commit one. // Otherwise, it requests a *new* client from the renderer, to act as // the target RenderFrameImpl's `NavigationClient`. // // ## Navigation Cancellation ## // Cancellation is signalled by closing the NavigationClient message pipe. // This will eventually trigger a connection error in the browser process, // which normally invokes NavigationRequest::OnRendererAbortedNavigation(). // // However, once the NavigationRequest reaches READY_TO_COMMIT in the browser // process, *only* the commit NavigationClient may cancel the navigation by // closing the message pipe. Thus, only navigations which reuse the RFH may be // cancelled (or more accurately, ignored) at this point. // // Unfortunately, this behavior is important for web compatibility: there are // sites which depend on a call to window.stop() or document.open() to cancel // a same-site navigation: see https://crbug.com/763106 for background. // // Note that using RenderDocument means that all cross-document navigations // will use a provisional RenderFrameImpl: as such, all cross-document // navigations with RenderDocument will ignore cancellation after // READY_TO_COMMIT. To handle this, all renderer-initiated navigations will // not enter the READY_TO_COMMIT stage until the task that initiated the // navigation finishes, to ensure that no renderer-initiated navigation // cancellation can take place after READY_TO_COMMIT. For more details, see // RendererCancellationThrottle. std::unique_ptr<NavigationClient> navigation_client_impl_; // Creates various media clients. MediaFactory media_factory_; blink::AssociatedInterfaceRegistry associated_interfaces_; // `remote_associated_interfaces_` cannot be constructed/bound at // RenderFrameImpl construction because it needs the underlying WebFrame to // get a TaskRunner. It also cannot be constructed/bound later in // `RenderFrame::Initialize()` (where we bind the `mojom::Frame` receiver), // because that happens *after* the `WebFrame` is initialized, and its // initialization relies on the interface provider being bound. So we stash // the pending remote here, and we bind it lazily in // `GetRemoteAssociatedInterfaces()`. mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider> pending_associated_interface_provider_remote_; std::unique_ptr<blink::AssociatedInterfaceProvider> remote_associated_interfaces_; // This flag is true while browser process is processing a pending navigation, // as a result of mojom::FrameHost::BeginNavigation call. It is reset when the // navigation is either committed or cancelled. bool is_requesting_navigation_ = false; // Set to true on the first time the RenderFrame started any navigation. // Note that when a frame is created it will trigger a navigation (either // synchronous to an empty document or asynchronous through the browser // process), so this will only stay false until we triggered that navigation. bool had_started_any_navigation_ = false; // The bindings types that have been enabled for this RenderFrame. BindingsPolicySet enabled_bindings_; // This boolean indicates whether JS bindings for Mojo should be enabled at // the time the next script context is created. bool enable_mojo_js_bindings_ = false; // This struct describes a set of MojoJs features to be enabled when the next // script context is created (requires MojoJs to be enabled). content::mojom::ExtraMojoJsFeaturesPtr mojo_js_features_; mojo::AssociatedRemote<mojom::FrameHost> frame_host_remote_; mojo::ReceiverSet<service_manager::mojom::InterfaceProvider> interface_provider_receivers_; mojo::ReceiverSet<blink::mojom::ResourceLoadInfoNotifier> resource_load_info_notifier_receivers_; // URLLoaderFactory instances used for subresource loading. // Depending on how the frame was created, |loader_factories_| could be: // * |HostChildURLLoaderFactoryBundle| for standalone frames, or // * |TrackedChildURLLoaderFactoryBundle| for frames opened by other frames. // // This must be updated only via SetLoaderFactoryBundle, which is called at a // certain timing - right before the new document is committed during // FrameLoader::CommitNavigation. scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories_; // Loader factory bundle is stored here temporary between CommitNavigation // and DidCommitNavigation calls. These happen synchronously one after // another. scoped_refptr<blink::ChildURLLoaderFactoryBundle> pending_loader_factories_; // The context used for background resource fetch. Used only when // BackgroundResourceFetch feature is enabled. scoped_refptr<blink::WebBackgroundResourceFetchAssets> background_resource_fetch_context_; // Used for background resource fetch. scoped_refptr<base::SequencedTaskRunner> background_resource_fetch_task_runner_; mojo::PendingRemote<blink::mojom::CodeCacheHost> pending_code_cache_host_; mojo::PendingRemote<blink::mojom::CodeCacheHost> pending_code_cache_host_for_background_; mojom::CookieManagerInfoPtr pending_cookie_manager_info_; mojom::StorageInfoPtr pending_storage_info_; // The storage key which |pending_storage_info_| is associated with. blink::StorageKey original_storage_key_; // AndroidOverlay routing token from the browser, if we have one yet. std::optional<base::UnguessableToken> overlay_routing_token_; // Used for devtools instrumentation and trace-ability. This token is // used to tag calls and requests in order to attribute them to the context // frame. // |devtools_frame_token_| is only defined by the browser and is never // sent back from the renderer in the control calls. base::UnguessableToken devtools_frame_token_; // True if the frame host wants stack traces on JavaScript console messages of // kError severity. bool want_error_message_stack_trace_ = false; // Used for tracking a frame's main frame document intersection and // replicating it to the browser when it changes. std::optional<gfx::Rect> main_frame_intersection_rect_; // Used for tracking the main frame viewport rectangle (i.e. dimensions and // scroll offset) within the main frame document. std::optional<gfx::Rect> main_frame_viewport_rect_; std::unique_ptr<blink::WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider_; RenderFrameMediaPlaybackOptions renderer_media_playback_options_; class MHTMLBodyLoaderClient; std::unique_ptr<MHTMLBodyLoaderClient> mhtml_body_loader_client_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override_for_test_; // When the browser asks the renderer to commit a navigation, it should always // result in a committed navigation reported via DidCommitProvisionalLoad(). // This is important because DidCommitProvisionalLoad() is responsible for // swapping in the provisional local frame during a cross-process navigation. // Since this involves updating state in both the browser process and the // renderer process, this assert ensures that the state remains synchronized // between the two processes. // // Note: there is one exception that can result in no commit happening. // Committing a navigation runs unload handlers, which can detach |this|. In // that case, it doesn't matter that the navigation never commits, since the // logical node for |this| has been removed from the DOM. enum class NavigationCommitState { // Represents the initial empty document. This is represented separately // from |kNone| because Blink does not report the commit of the initial // empty document in a newly created frame. However, note that there are // some surprising quirks: // // <iframe></iframe> // // will *not* be in the |kInitialEmptyDocument| state: while it initially // starts at the initial empty document, the initial empty document is then // synchronously replaced with a navigation to about:blank. In contrast: // // <iframe src="https://slow.example.com"></iframe> // // will be in |kInitialEmptyDocument| until the navigation to // https://slow.example.com commits. kInitialEmptyDocument, // No commit in progress. This state also implies that the frame is not // displaying the initial empty document. kNone, // Marks that an active commit attempt is on the stack. kWillCommit, // Marks an active commit attempt as successful. kDidCommit, }; enum MayReplaceInitialEmptyDocumentTag { kMayReplaceInitialEmptyDocument, }; class CONTENT_EXPORT AssertNavigationCommits { public: // Construct a new scoper to verify that a navigation commit attempt // succeeds. Asserts that: // - no navigation is in progress // - the frame is not displaying the initial empty document. explicit AssertNavigationCommits(RenderFrameImpl* frame); // Similar to the previous constructor but allows transitions from the // initial empty document. explicit AssertNavigationCommits(RenderFrameImpl* frame, MayReplaceInitialEmptyDocumentTag); ~AssertNavigationCommits(); private: explicit AssertNavigationCommits( RenderFrameImpl* frame, bool allow_transition_from_initial_empty_document); const base::WeakPtr<RenderFrameImpl> frame_; }; NavigationCommitState navigation_commit_state_ = NavigationCommitState::kInitialEmptyDocument; // Timer used to delay the updating of frame state. base::OneShotTimer delayed_state_sync_timer_; // Whether content state (such as form state, scroll position and page // contents) should be sent to the browser immediately. This is normally // false, but set to true by some tests. bool send_content_state_immediately_ = false; // The RenderFrameImpl can be created in 2 modes. // // 1. The associated WebFrameWidget and its compositor is initialized at // creation time. This is default mode. // // 2. The associated WebFrameWidget and its compositor is initialized at // commit time. This is done for local RF->local RF navigations to reuse // the compositor from the previous RFH. This is purely a performance // optimization. // // When in mode 2, the parameters to create the WebFrameWidget (which are // part of the IPC that created this frame) are cached until commit to lazily // create the WebFrameWidget. mojom::CreateFrameWidgetParamsPtr widget_params_for_lazy_widget_creation_; // Set when this RenderFrame is being swapped for // `provisional_frame_for_local_root_swap_`. base::WeakPtr<RenderFrameImpl> provisional_frame_for_local_root_swap_ = nullptr; // Set if this RenderFrameImpl is for a main frame which is not top-level. const bool is_for_nested_main_frame_; base::WeakPtrFactory<RenderFrameImpl> weak_factory_{this}; }; } // namespace content #endif // CONTENT_RENDERER_RENDER_FRAME_IMPL_H_