chromium/content/browser/display_cutout/display_cutout_host_impl_unittest.cc

// 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.

#include "content/browser/display_cutout/display_cutout_host_impl.h"

#include "base/memory/raw_ptr.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/features.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace content {

namespace {

class TestDisplayCutoutHostImpl : public DisplayCutoutHostImpl {
 public:
  explicit TestDisplayCutoutHostImpl(WebContentsImpl* web_contents_impl)
      : DisplayCutoutHostImpl(web_contents_impl) {}

  void ResetSafeArea() {
    did_send_safe_area_ = false;
    safe_area_insets_ = gfx::Insets(0);
  }

  bool did_send_safe_area() { return did_send_safe_area_; }
  gfx::Insets safe_area_insets() { return safe_area_insets_; }

 protected:
  // Send the safe area insets to a |RenderFrameHost|.
  void SendSafeAreaToFrame(RenderFrameHost* rfh, gfx::Insets insets) override {
    did_send_safe_area_ = true;
    safe_area_insets_ = insets;
    DisplayCutoutHostImpl::SendSafeAreaToFrame(rfh, insets);
  }

 private:
  bool did_send_safe_area_ = false;
  gfx::Insets safe_area_insets_;
};

}  // namespace

class DisplayCutoutHostImplTest : public RenderViewHostTestHarness {
 protected:
  void SetUp() override {
    RenderViewHostTestHarness::SetUp();
    SetContents(CreateTestWebContents());

    std::unique_ptr<TestDisplayCutoutHostImpl> test_display_cutout_host_impl =
        absl::make_unique<TestDisplayCutoutHostImpl>(test_web_contents());
    test_display_cutout_host_ = test_display_cutout_host_impl.get();
    test_web_contents()->SetSafeAreaInsetsHost(
        std::move(test_display_cutout_host_impl));
  }

  TestWebContents* test_web_contents() const {
    return static_cast<TestWebContents*>(web_contents());
  }

  TestDisplayCutoutHostImpl* test_display_cutout_host() const {
    return test_display_cutout_host_;
  }

  void ResetSafeArea() { test_display_cutout_host()->ResetSafeArea(); }

  void NavigateToCover() {
    FocusWebContentsOnMainFrame();
    // Simulate window insets changing, e.g. java's
    // DisplayCutoutController#onSafeAreaChanged notified from InsetObserver.
    test_web_contents()->SetDisplayCutoutSafeArea(gfx::Insets(42));
    NavigateAndCommit(GURL("www.viewportFitCover.com"));
    test_web_contents()->NotifyViewportFitChanged(
        blink::mojom::ViewportFit::kCover);
  }

  void NavigateToAuto() {
    FocusWebContentsOnMainFrame();
    test_web_contents()->SetDisplayCutoutSafeArea(gfx::Insets(0));
    NavigateAndCommit(GURL("www.viewportFitAuto.com"));
    test_web_contents()->NotifyViewportFitChanged(
        blink::mojom::ViewportFit::kAuto);
  }

 private:
  raw_ptr<TestDisplayCutoutHostImpl> test_display_cutout_host_;
};

TEST_F(DisplayCutoutHostImplTest, AutoToCover) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures(
      /*enabled_features=*/{features::kDrawCutoutEdgeToEdge},
      /*disabled_features=*/{});

  ResetSafeArea();
  NavigateToAuto();
  EXPECT_TRUE(test_display_cutout_host()->did_send_safe_area());
  EXPECT_EQ(0, test_display_cutout_host()->safe_area_insets().top())
      << "No Display Cutout, so the top inset should have been zero";

  ResetSafeArea();
  NavigateToCover();
  EXPECT_TRUE(test_display_cutout_host()->did_send_safe_area());
  EXPECT_NE(0, test_display_cutout_host()->safe_area_insets().top())
      << "The Display Cutout should have caused a non-zero top inset";
}

TEST_F(DisplayCutoutHostImplTest, CoverToAuto) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures(
      /*enabled_features=*/{features::kDrawCutoutEdgeToEdge},
      /*disabled_features=*/{});

  ResetSafeArea();
  NavigateToCover();
  EXPECT_TRUE(test_display_cutout_host()->did_send_safe_area());
  EXPECT_NE(0, test_display_cutout_host()->safe_area_insets().top())
      << "The Display Cutout should have caused a non-zero top inset";

  ResetSafeArea();
  NavigateToAuto();
  EXPECT_TRUE(test_display_cutout_host()->did_send_safe_area());
  EXPECT_EQ(0, test_display_cutout_host()->safe_area_insets().top())
      << "No Display Cutout, so the top inset should have been zero";
}

}  // namespace content