chromium/ui/aura/window_tree_host_unittest.cc

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/window_tree_host.h"

#include "base/containers/contains.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "ui/aura/native_window_occlusion_tracker.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/aura_test_utils.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/window_event_dispatcher_test_api.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/test/test_event_rewriter.h"
#include "ui/platform_window/stub/stub_window.h"

namespace aura {

namespace {

// A convenient wrapper that makes it easy to invoke this method inside an
// EXPECT_EQ statement.
gfx::Point ConvertDIPToPixels(const WindowTreeHost* host, gfx::Point point) {}

// A convenient wrapper that makes it easy to invoke this method inside an
// EXPECT_EQ statement.
gfx::PointF ConvertDIPToPixels(const WindowTreeHost* host, gfx::PointF point) {}

// A convenient wrapper that makes it easy to invoke this method inside an
// EXPECT_EQ statement.
gfx::Point ConvertPixelsToDIP(const WindowTreeHost* host, gfx::Point point) {}

// A convenient wrapper that makes it easy to invoke this method inside an
// EXPECT_EQ statement.
gfx::PointF ConvertPixelsToDIP(const WindowTreeHost* host, gfx::PointF point) {}

}  // namespace

WindowTreeHostTest;

TEST_F(WindowTreeHostTest, DPIWindowSize) {}

TEST_F(WindowTreeHostTest,
       ShouldHaveExactRootWindowBoundsWithDisplayRotation1xScale) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(WindowTreeHostTest, HoldPointerMovesOnChildResizing) {
  aura::WindowEventDispatcher* dispatcher = host()->dispatcher();

  aura::test::WindowEventDispatcherTestApi dispatcher_api(dispatcher);

  EXPECT_FALSE(dispatcher_api.HoldingPointerMoves());

  // Signal to the ui::Compositor that a child is resizing. This will
  // immediately trigger input throttling.
  host()->compositor()->OnChildResizing();

  // Pointer moves should be throttled until the next commit. This has the
  // effect of prioritizing the resize event above other operations in aura.
  EXPECT_TRUE(dispatcher_api.HoldingPointerMoves());

  // Wait for a CompositorFrame to be activated.
  ui::DrawWaiterForTest::WaitForCompositingEnded(host()->compositor());

  // Pointer moves should be routed normally after commit.
  EXPECT_FALSE(dispatcher_api.HoldingPointerMoves());
}
#endif

#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Tests if scale factor changes take effect. Previously a scale factor change
// wouldn't take effect without a bounds change. For context see
// https://crbug.com/1087626
TEST_F(WindowTreeHostTest, ShouldHandleTextScale) {}
#endif

TEST_F(WindowTreeHostTest, NoRewritesPostIME) {}

TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectScaleFactor) {}

TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectRotation) {}

TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldWorkWithPointF) {}

TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectScaleFactor) {}

TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectRotation) {}

TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldWorkWithPointF) {}

class TestWindow : public ui::StubWindow {};

class TestWindowTreeHost : public WindowTreeHostPlatform {};

TEST_F(WindowTreeHostTest, LostCaptureDuringTearDown) {}

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS)
class WindowTreeHostWithReleaseTest : public test::AuraTestBase {
 public:
  // AuraTestBase:
  void SetUp() override {
    scoped_feature_list_.InitWithFeaturesAndParameters(
        {
#if BUILDFLAG(IS_WIN)
            {features::kCalculateNativeWinOcclusion, {}},
#endif
            {features::kApplyNativeOcclusionToCompositor,
             {{features::kApplyNativeOcclusionToCompositorType.name,
               features::kApplyNativeOcclusionToCompositorTypeRelease}}},
            // Disable the headless check as the bots run with CHROME_HEADLESS
            // set.
            {features::kAlwaysTrackNativeWindowOcclusionForTest, {}}},
        {});
    AuraTestBase::SetUp();
  }

  void TearDown() override { test::AuraTestBase::TearDown(); }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_F(WindowTreeHostWithReleaseTest, ToggleOccluded) {
  host()->Show();
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

TEST_F(WindowTreeHostWithReleaseTest, ToggleHidden) {
  host()->Show();
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::HIDDEN, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

TEST_F(WindowTreeHostWithReleaseTest, VideoCaptureLockForcesVisible) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
      host()->CreateVideoCaptureLock();
  EXPECT_TRUE(host()->compositor()->IsVisible());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();
  EXPECT_FALSE(host()->compositor()->IsVisible());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

TEST_F(WindowTreeHostWithReleaseTest, VideoCaptureLockAffectsOcclusionState) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
      host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // It should return to occluded after.
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());

  // Now try the same thing for the hidden occlusion state:
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::HIDDEN, {});
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // It should return to hidden after.
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

class WindowTreeHostWithThrottleTest : public test::AuraTestBase {
 public:
  // AuraTestBase:
  void SetUp() override {
    // Disable the headless check as the bots run with CHROME_HEADLESS set.
    scoped_feature_list_.InitWithFeaturesAndParameters(
        {
#if BUILDFLAG(IS_WIN)
            {features::kCalculateNativeWinOcclusion, {}},
#endif
            {features::kApplyNativeOcclusionToCompositor,
             {{features::kApplyNativeOcclusionToCompositorType.name,
               features::kApplyNativeOcclusionToCompositorTypeThrottle}}},
            // Disable the headless check as the bots run with CHROME_HEADLESS
            // set.
            {features::kAlwaysTrackNativeWindowOcclusionForTest, {}},
        },
        {});
    AuraTestBase::SetUp();
  }

  void TearDown() override { test::AuraTestBase::TearDown(); }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_F(WindowTreeHostWithThrottleTest, Basic) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

TEST_F(WindowTreeHostWithThrottleTest, CallHideDirectly) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  host()->Hide();
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  EXPECT_FALSE(host()->compositor()->IsVisible());
}

TEST_F(WindowTreeHostWithThrottleTest, VideoCaptureLockAffectsOcclusionState) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());

  std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
      host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  lock.reset();

  // It should return to occluded after.
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());

  // Now try the same thing for the hidden occlusion state:
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::HIDDEN, {});
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());

  lock = host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  lock.reset();

  // It should return to hidden after.
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
}

class WindowTreeHostWithThrottleAndReleaseTest : public test::AuraTestBase {
 public:
  // AuraTestBase:
  void SetUp() override {
    scoped_feature_list_.InitWithFeaturesAndParameters(
        {
#if BUILDFLAG(IS_WIN)
            {features::kCalculateNativeWinOcclusion, {}},
#endif
            {features::kApplyNativeOcclusionToCompositor,
             {{features::kApplyNativeOcclusionToCompositorType.name,
               features::
                   kApplyNativeOcclusionToCompositorTypeThrottleAndRelease}}},
            // Disable the headless check as the bots run with CHROME_HEADLESS
            // set.
            {features::kAlwaysTrackNativeWindowOcclusionForTest, {}},
        },
        {});
    AuraTestBase::SetUp();
  }

  void TearDown() override { test::AuraTestBase::TearDown(); }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_F(WindowTreeHostWithThrottleAndReleaseTest, ToggleOccluded) {
  host()->Show();
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
}

TEST_F(WindowTreeHostWithThrottleAndReleaseTest, ToggleHidden) {
  host()->Show();
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::HIDDEN, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
}

TEST_F(WindowTreeHostWithThrottleAndReleaseTest, DestroyWhileThrottled) {
  host()->Show();
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  // Expect not to crash after destroying WindowTreeHost after this.
}

TEST_F(WindowTreeHostWithThrottleAndReleaseTest,
       VideoCaptureLockForcesVisible) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_FALSE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
      host()->CreateVideoCaptureLock();
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
  lock.reset();
  EXPECT_FALSE(host()->compositor()->IsVisible());
  EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_TRUE(host()->compositor()->IsVisible());
  EXPECT_TRUE(test::GetThrottledHosts().empty());
}

TEST_F(WindowTreeHostWithThrottleAndReleaseTest,
       VideoCaptureLockAffectsOcclusionState) {
  ASSERT_TRUE(NativeWindowOcclusionTracker::
                  IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  // This test needs to drive native occlusion. If native occlusion is
  // used, it'll conflict with this test.
  NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  host()->Show();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
      host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // It should return to occluded after.
  EXPECT_EQ(Window::OcclusionState::OCCLUDED,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());

  // Now try the same thing for the hidden occlusion state:
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::HIDDEN, {});
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  // VideoCaptureLock should force this to visible.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // It should return to hidden after.
  EXPECT_EQ(Window::OcclusionState::HIDDEN,
            host()->GetNativeWindowOcclusionState());
  EXPECT_FALSE(host()->compositor()->IsVisible());

  lock = host()->CreateVideoCaptureLock();
  host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
  lock.reset();

  // We set the native occlusion state to visible, this should persist after
  // destroying the capture lock.
  EXPECT_EQ(Window::OcclusionState::VISIBLE,
            host()->GetNativeWindowOcclusionState());
  EXPECT_TRUE(host()->compositor()->IsVisible());
}

#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS)

}  // namespace aura