blob: bc7471a764e18255d1b7103c59ae05f266a171c2 [file] [log] [blame]
// 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_