| // Copyright 2023 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_DISPLAY_CUTOUT_SAFE_AREA_INSETS_HOST_IMPL_H_ |
| #define CONTENT_BROWSER_DISPLAY_CUTOUT_SAFE_AREA_INSETS_HOST_IMPL_H_ |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/browser/display_cutout/safe_area_insets_host.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/document_user_data.h" |
| #include "content/public/browser/render_frame_host_receiver_set.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "third_party/blink/public/mojom/page/display_cutout.mojom.h" |
| #include "ui/gfx/geometry/insets.h" |
| |
| namespace content { |
| |
| class RenderFrameHostImpl; |
| class WebContentsImpl; |
| |
| // Handles changes to Safe Area Insets (SAI) by monitoring |
| // navigations within a `WebContents` and hosting a connection |
| // to Blink. See the base class `SafeAreaInsetsHost` for context. |
| |
| // Tracks the viewport-fit value associated with each Blink Document |
| // as `WebContents` are updated through navigation etc. As of 2023 each |
| // RenderFrameHost may correspond to one or more documents during in-site |
| // navigation, so this class maps the viewport-fit value of a document to the |
| // associated RFH and updates the owning `WebContents` when it changes. |
| // Note that subframes may acquire fullscreen so the viewport-fit from that |
| // frame may change the insets. |
| // |
| // This class ensures there will be only one frame that receives the current |
| // SAI, with this rule: |
| // * When a fullscreen frame exists, the fullscreen frame will take the SAI |
| // * When no fullscreen frame exists, the primary main frame will take the SAI |
| // * When the frame that takes SAI changes, the SAI in the previous frame will |
| // be reset. |
| class CONTENT_EXPORT SafeAreaInsetsHostImpl : public SafeAreaInsetsHost { |
| public: |
| explicit SafeAreaInsetsHostImpl(WebContentsImpl*); |
| |
| SafeAreaInsetsHostImpl(const SafeAreaInsetsHostImpl&) = delete; |
| SafeAreaInsetsHostImpl& operator=(const SafeAreaInsetsHostImpl&) = delete; |
| |
| ~SafeAreaInsetsHostImpl() override; |
| |
| void DidAcquireFullscreen(RenderFrameHost* rfh) override; |
| void DidExitFullscreen() override; |
| void DidFinishNavigation(NavigationHandle* navigation_handle) override; |
| void RenderFrameDeleted(RenderFrameHost* rfh) override {} |
| void RenderFrameCreated(RenderFrameHost* rfh) override {} |
| |
| void SetDisplayCutoutSafeArea(gfx::Insets insets) override; |
| |
| protected: |
| // SafeAreaInsetsHost override. |
| void ViewportFitChangedForFrame(RenderFrameHost* rfh, |
| blink::mojom::ViewportFit value) override; |
| void ComplexSafeAreaConstraintChangedForFrame(RenderFrameHost* rfh, |
| bool has_constraint) override; |
| |
| // Get the stored viewport fit value for a frame or kAuto if there is no |
| // stored value. |
| // Protected for testing only. |
| blink::mojom::ViewportFit GetValueOrDefault(RenderFrameHost* rfh) const; |
| |
| // Sets the stored viewport fit value / safe area constraint value for a |
| // frame, deleting the UserData if it's no longer needed. |
| // Protected for testing only. |
| void SetViewportFitValue(RenderFrameHost* rfh, |
| blink::mojom::ViewportFit value); |
| |
| void SetSafeAreaConstraintValue(RenderFrameHost* rfh, bool has_constraint); |
| bool GetSafeAreaConstraintOrDefault(RenderFrameHost* rfh) const; |
| |
| private: |
| static constexpr gfx::Insets kZeroInsets = gfx::Insets(); |
| |
| friend class TestSafeAreaInsetsHostImpl; |
| |
| // Checks if the active `RenderFrameHost` has changed, and notifies |
| // Blink about the current safe area, and WebContents observers if needed. |
| void MaybeActiveRenderFrameHostChanged(); |
| |
| // Clears the insets on the active frame. This should particularly be used |
| // when switching frames during a transition into or out of fullscreen mode. |
| void ClearSafeAreaInsetsForActiveFrame(); |
| |
| // Send the safe area insets to the current frame if all conditions are met. |
| void MaybeSendSafeAreaToFrame(RenderFrameHost* rfh, gfx::Insets insets); |
| |
| // Returns the current active `RenderFrameHost`: the current RFH or the |
| // fullscreen RFH when in Fullscreen mode. May return `nullptr` during |
| // startup. |
| RenderFrameHostImpl* active_render_frame_host() { return active_rfh_.get(); } |
| |
| // Stores the current primary main `RenderFrameHost`. Never `nullptr` except |
| // during startup. |
| base::WeakPtr<RenderFrameHostImpl> current_rfh_; |
| |
| // Stores the `RenderFrameHost` being displayed in fullscreen, and is |
| // `nullptr` when not in fullscreen. |
| base::WeakPtr<RenderFrameHostImpl> fullscreen_rfh_; |
| |
| // Stores the current active `RenderFrameHost` that received the safe area |
| // insets. This could be either the `current_rfh`, or `fullscreen_rfh_` |
| // if in fullscreen mode. Caching this to keep track when the active |
| // `RenderFrameHost` changes. Should only be accessed in |
| // `MaybeActiveRenderFrameHostChanged()`; other code should use |
| // `active_render_frame_host()` instead. |
| base::WeakPtr<RenderFrameHostImpl> active_rfh_; |
| |
| // Stores the viewport-fit value that's active for this WebContents. |
| blink::mojom::ViewportFit active_viewport_fit_ = |
| blink::mojom::ViewportFit::kAuto; |
| // Stores the active value from |ComplexSafeAreaConstraintChangedForFrame| for |
| // the web contents. |
| bool active_has_constraint_ = false; |
| |
| // The current insets. |
| gfx::Insets insets_; |
| |
| // Whether or not non-zero insets have been sent to a frame over the course of |
| // this SafeAreaInsetsHost. |
| bool has_sent_non_zero_insets_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_DISPLAY_CUTOUT_SAFE_AREA_INSETS_HOST_IMPL_H_ |