| // Copyright 2026 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_BROWSER_SURFACE_EMBED_SURFACE_EMBED_CONNECTOR_IMPL_H_ |
| #define CONTENT_BROWSER_SURFACE_EMBED_SURFACE_EMBED_CONNECTOR_IMPL_H_ |
| |
| #include <memory> |
| #include <optional> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "components/viz/common/surfaces/surface_info.h" |
| #include "content/browser/renderer_host/frame_connector.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/global_routing_id.h" |
| #include "content/public/browser/surface_embed_connector.h" |
| #include "third_party/blink/public/common/frame/frame_visual_properties.h" |
| #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-forward.h" |
| #include "third_party/blink/public/mojom/frame/lifecycle.mojom.h" |
| #include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom.h" |
| #include "ui/accessibility/ax_node_id_forward.h" |
| #include "ui/accessibility/ax_tree_id.h" |
| #include "ui/base/cursor/cursor.h" |
| #include "ui/compositor/compositor.h" |
| #include "ui/display/screen_infos.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| |
| namespace input { |
| |
| class RenderWidgetHostInputEventRouter; |
| |
| } // namespace input |
| |
| namespace content { |
| |
| class FrameTree; |
| class RenderFrameHost; |
| class RenderFrameHostImpl; |
| class RenderWidgetHostImpl; |
| class RenderViewHostDelegateView; |
| class RenderWidgetHostViewChildFrame; |
| class TextInputManager; |
| class WebContentsDelegate; |
| class WebContentsImpl; |
| class WebContentsView; |
| |
| class CONTENT_EXPORT SurfaceEmbedConnectorImpl |
| : public SurfaceEmbedConnector, |
| public FrameConnector { |
| public: |
| ~SurfaceEmbedConnectorImpl() override; |
| |
| static bool ContainsOrIsFocusedWebContents(WebContentsImpl* web_contents); |
| |
| WebContentsView* GetParentWebContentsView() const; |
| RenderViewHostDelegateView* GetParentRenderViewHostDelegateView() const; |
| |
| // Returns the first WebContentsDelegate found in the embedding chain. |
| // If this connector has a parent WebContents, it delegates the query |
| // to the parent; otherwise it returns nullptr (since the child's delegate |
| // was already checked and must have been null to reach here). |
| WebContentsDelegate* GetFirstWebContentsDelegate() const; |
| |
| // Returns the InputEventRouter appropriate for the child web contents to |
| // register with. Note that this is the parent web contents's |
| // InputEventRouter, and this will return nullptr if the parent web contents |
| // is null. |
| input::RenderWidgetHostInputEventRouter* GetInputEventRouter(); |
| |
| // Returns the parent web contents's TextInputManager, or nullptr if the |
| // parent web contents is null. |
| TextInputManager* GetTextInputManager(); |
| |
| // SurfaceEmbedConnector: |
| SurfaceEmbedConnector::Delegate* GetDelegate() override; |
| void OnSynchronizeVisualProperties( |
| const blink::FrameVisualProperties& visual_properties) override; |
| void UpdateRenderThrottlingStatus(bool is_throttled, |
| bool subtree_throttled, |
| bool display_locked) override; |
| const viz::FrameSinkId& GetFrameSinkId() const override; |
| double GetCssZoomFactorForTesting() override; |
| const gfx::Size& GetLocalFrameSizeInPixelsForTesting() override; |
| bool IsThrottledForTesting() override; |
| bool IsSubtreeThrottledForTesting() override; |
| bool IsDisplayLockedForTesting() override; |
| void SetParentAccessibilityInfo(ui::AXNodeID ax_node_id, |
| const ui::AXTreeID& ax_tree_id) override; |
| ui::AXTreeID GetParentAXTreeID() const override; |
| |
| // FrameConnector: |
| void SetKeepSurfaceAlive(bool keep_alive) override; |
| bool IsKeepingAlive() const override; |
| void SetView(RenderWidgetHostViewChildFrame* view, |
| bool allow_paint_holding) override; |
| RenderWidgetHostViewBase* GetParentRenderWidgetHostView() override; |
| RenderWidgetHostViewBase* GetRootRenderWidgetHostView() override; |
| void RenderProcessGone() override; |
| void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override; |
| void SendIntrinsicSizingInfoToParent( |
| blink::mojom::IntrinsicSizingInfoPtr) override; |
| void SynchronizeVisualProperties( |
| const blink::FrameVisualProperties& visual_properties, |
| bool propagate) override; |
| void UpdateCursor(const ui::Cursor& cursor) override; |
| RootViewFocusState HasFocus() override; |
| void FocusRootView() override; |
| blink::mojom::PointerLockResult LockPointer( |
| bool request_unadjusted_movement) override; |
| blink::mojom::PointerLockResult ChangePointerLock( |
| bool request_unadjusted_movement) override; |
| void UnlockPointer() override; |
| bool HasSize() override; |
| const display::ScreenInfos& GetScreenInfos() override; |
| const viz::LocalSurfaceId& GetLocalSurfaceId() override; |
| const blink::mojom::ViewportIntersectionState& GetIntersectionState() |
| override; |
| const gfx::Rect& GetRectInParentViewInDip() override; |
| const gfx::Size& GetLocalFrameSizeInDip() override; |
| const gfx::Size& GetLocalFrameSizeInPixels() override; |
| double GetCssZoomFactor() override; |
| void EnableAutoResize(const gfx::Size& min_size, |
| const gfx::Size& max_size) override; |
| void DisableAutoResize() override; |
| bool IsInert() override; |
| cc::TouchAction InheritedEffectiveTouchAction() override; |
| bool IsHidden() override; |
| bool IsThrottled() override; |
| bool IsSubtreeThrottled() override; |
| bool IsDisplayLocked() override; |
| void DidUpdateVisualProperties( |
| const cc::RenderFrameMetadata& metadata) override; |
| void SetVisibilityForChildViews(bool visible) override; |
| void SetLocalFrameSize(const gfx::Size& local_frame_size) override; |
| void SetRectInParentView(const gfx::Rect& rect_in_parent_view) override; |
| void OnVisibilityChanged(blink::mojom::FrameVisibility visibility) override; |
| bool IsVisible() override; |
| void DelegateWasShown() override; |
| Visibility EmbedderVisibility() override; |
| |
| // input::ChildFrameInputHelper::Delegate: |
| input::RenderWidgetHostViewInput* GetParentViewInput() override; |
| input::RenderWidgetHostViewInput* GetRootViewInput() override; |
| |
| void UpdateAccessibilityTree(); |
| |
| // Updates the `view_` member to track the current RenderWidgetHostView |
| // associated with the child WebContents. |
| void UpdateViewForCurrentRenderFrameHost(); |
| |
| // Called by WebContentsImpl after the connector is set. Notifies the parent |
| // WebContents and updates the view. |
| void OnAttachedToParent(); |
| |
| // Called by WebContentsImpl before the connector is cleared. Notifies the |
| // parent WebContents. |
| void OnDetachedFromParent(); |
| |
| // Returns nullptr if the focus is outside of this connector's child |
| // WebContents. |
| FrameTree* GetFocusFrameTreeIfContainsFocus(); |
| void SetFocusedFrameTree(FrameTree* frame_tree_to_focus); |
| void ClearFocusOnInnerWebContents(); |
| |
| // Returns true if any WebContents in the parent chain has a pointer lock |
| // widget. |
| bool HasPointerLockWidgetInParentChain() const; |
| |
| // Sets the pointer lock widget for all WebContents in the parent chain. |
| void SetPointerLockWidgetInParentChain(RenderWidgetHostImpl* widget); |
| |
| // Returns true if the parent WebContents (or any ancestor) has a pointer lock |
| // for the given `render_widget_host`. |
| bool HasPointerLock(RenderWidgetHostImpl* render_widget_host) const; |
| |
| // Returns the pointer lock widget from the parent WebContents (or any |
| // ancestor) if it exists and is locked. |
| RenderWidgetHostImpl* GetPointerLockWidget() const; |
| |
| private: |
| class WCObserver; |
| class ParentWCObserver; |
| |
| friend class SurfaceEmbedConnector; |
| friend class SurfaceEmbedConnectorImplBrowserTest; |
| friend class SurfaceEmbedConnectorWebContentsBrowserTest; |
| |
| // `child_web_contents` will have ownership of this. `delegate` is required to |
| // outlive this. Assumes that `child_web_contents` is non-null. |
| SurfaceEmbedConnectorImpl(WebContents* child_web_contents, |
| WebContents* parent_web_contents, |
| RenderFrameHost* embedder_rfh, |
| SurfaceEmbedConnector::Delegate* delegate); |
| |
| static WebContentsImpl* GetParentWebContents(WebContentsImpl* web_contents); |
| static WebContentsImpl* GetRootWebContents(WebContentsImpl* web_contents); |
| |
| WebContentsImpl* parent_web_contents() const; |
| WebContentsImpl* child_web_contents() const { |
| return child_web_contents_.get(); |
| } |
| |
| // Resets the rect and the viz::LocalSurfaceId of the connector to ensure the |
| // unguessable surface ID is not reused after a navigation. |
| void ResetRectInParentView(); |
| |
| RenderFrameHostImpl* current_child_frame_host() const; |
| |
| void ParentVisibilityChanged(Visibility visibility); |
| void UpdateChildVisibility(); |
| |
| // Observes the child WebContents to send notifications to the connector. |
| std::unique_ptr<WCObserver> wc_observer_; |
| // Observes the parent WebContents to propagate visibility changes. |
| std::unique_ptr<ParentWCObserver> parent_wc_observer_; |
| |
| raw_ptr<SurfaceEmbedConnector::Delegate> delegate_ = nullptr; |
| |
| raw_ptr<WebContentsImpl> child_web_contents_; // Owns this object. |
| // WeakPtr to the parent WebContents. Automatically clears to nullptr when the |
| // observed parent is destroyed, safely notifying all consumers. |
| base::WeakPtr<WebContents> parent_web_contents_; |
| // The RenderFrameHost in the parent that hosts the embed element. |
| base::WeakPtr<RenderFrameHostImpl> embedder_rfh_; |
| raw_ptr<RenderWidgetHostViewChildFrame> view_ = nullptr; |
| |
| // The last received FrameSinkId from the guest WebContents's view. |
| viz::FrameSinkId frame_sink_id_; |
| |
| ui::AXNodeID container_accessibility_node_id_ = ui::kInvalidAXNodeID; |
| ui::AXTreeID container_accessibility_tree_id_; |
| |
| // The AXTreeID of the parent (embedder) accessibility tree that the child's |
| // tree is currently stitched into, or ui::AXTreeIDUnknown() when not |
| // stitched. Established by UpdateAccessibilityTree() and read back by |
| // RenderFrameHostImpl (via RenderFrameHostDelegate::GetSurfaceEmbedConnector) |
| // to answer the embedded child main frame's AX-parent queries. |
| ui::AXTreeID embed_parent_ax_tree_id_; |
| |
| // The last received LocalSurfaceId from the SurfaceEmbed. |
| viz::LocalSurfaceId local_surface_id_; |
| |
| // Visibility state of the corresponding surface embed element in parent |
| // process which is set through CSS or scrolling. |
| blink::mojom::FrameVisibility visibility_ = |
| blink::mojom::FrameVisibility::kRenderedInViewport; |
| |
| display::ScreenInfos screen_infos_; |
| blink::mojom::ViewportIntersectionState intersection_state_; |
| gfx::Rect rect_in_parent_view_in_dip_; |
| gfx::Size local_frame_size_in_dip_; |
| gfx::Size local_frame_size_in_pixels_; |
| |
| gfx::Size last_received_local_frame_size_; |
| double last_received_css_zoom_factor_ = 1; |
| double last_received_zoom_level_ = 0.0; |
| bool has_size_ = false; |
| |
| // TODO(crbug.com/493315755): Update the properties as appropriate. (Currently |
| // they are not updated after initialization.) |
| bool is_inert_ = false; |
| cc::TouchAction inherited_effective_touch_action_ = cc::TouchAction::kAuto; |
| bool is_throttled_ = false; |
| bool subtree_throttled_ = false; |
| bool display_locked_ = false; |
| |
| void MaybeRefreshKeepSurfaceAlive(); |
| |
| ui::Compositor::ScopedKeepSurfaceAliveCallback keep_surface_alive_; |
| bool should_keep_alive_ = false; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_SURFACE_EMBED_SURFACE_EMBED_CONNECTOR_IMPL_H_ |