#include "third_party/blink/renderer/platform/widget/compositing/render_frame_metadata_observer_impl.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "cc/mojom/render_frame_metadata.mojom-blink.h"
#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
namespace {
ACTION_P(InvokeClosure, closure) { … }
}
class MockRenderFrameMetadataObserverClient
: public cc::mojom::blink::RenderFrameMetadataObserverClient { … };
class RenderFrameMetadataObserverImplTest : public testing::Test { … };
TEST_F(RenderFrameMetadataObserverImplTest, ShouldSendFrameToken) { … }
#if BUILDFLAG(IS_ANDROID)
TEST_F(RenderFrameMetadataObserverImplTest, ShouldSendFrameTokenOnAndroid) {
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = 1337;
cc::RenderFrameMetadata render_frame_metadata;
render_frame_metadata.root_scroll_offset = gfx::PointF(0.f, 1.f);
render_frame_metadata.root_layer_size = gfx::SizeF(100.f, 100.f);
render_frame_metadata.scrollable_viewport_size = gfx::SizeF(100.f, 50.f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_TRUE(compositor_frame_metadata.send_frame_token_to_embedder);
{
base::RunLoop run_loop;
EXPECT_CALL(client(),
OnRenderFrameMetadataChanged(1337, render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.f, 0.f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_FALSE(compositor_frame_metadata.send_frame_token_to_embedder);
{
base::RunLoop run_loop;
EXPECT_CALL(client(),
OnRenderFrameMetadataChanged(0u, render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
}
TEST_F(RenderFrameMetadataObserverImplTest, SendRootScrollsForAccessibility) {
const uint32_t expected_frame_token = 1337;
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = expected_frame_token;
cc::RenderFrameMetadata render_frame_metadata;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_TRUE(compositor_frame_metadata.send_frame_token_to_embedder);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.0f, 100.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
render_frame_metadata.is_scroll_offset_at_top =
!render_frame_metadata.is_scroll_offset_at_top;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
observer_impl().UpdateRootScrollOffsetUpdateFrequency(
cc::mojom::RootScrollOffsetUpdateFrequency::kAllUpdates);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.0f, 200.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRootScrollOffsetChanged(
*(render_frame_metadata.root_scroll_offset)))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.is_scroll_offset_at_top =
!render_frame_metadata.is_scroll_offset_at_top;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
}
TEST_F(RenderFrameMetadataObserverImplTest,
DoNotSendRootScrollOffsetByDefault) {
const uint32_t expected_frame_token = 1337;
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = expected_frame_token;
cc::RenderFrameMetadata render_frame_metadata;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.0f, 100.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
render_frame_metadata.root_scroll_offset->set_y(200.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
render_frame_metadata.root_scroll_offset->set_y(300.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.Times(0);
}
TEST_F(RenderFrameMetadataObserverImplTest, DoNotSendExtraRootScrollOffset) {
const uint32_t expected_frame_token = 1337;
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = expected_frame_token;
cc::RenderFrameMetadata render_frame_metadata;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
observer_impl().UpdateRootScrollOffsetUpdateFrequency(
cc::mojom::RootScrollOffsetUpdateFrequency::kAllUpdates);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.0f, 200.0f);
render_frame_metadata.is_scroll_offset_at_top =
!render_frame_metadata.is_scroll_offset_at_top;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_CALL(client(), OnRootScrollOffsetChanged(
*(render_frame_metadata.root_scroll_offset)))
.Times(0);
}
TEST_F(RenderFrameMetadataObserverImplTest, SendRootScrollOffsetOnScrollEnd) {
ScopedCCTNewRFMPushBehaviorForTest feature(true);
const uint32_t expected_frame_token = 1337;
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = expected_frame_token;
cc::RenderFrameMetadata render_frame_metadata;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
observer_impl().UpdateRootScrollOffsetUpdateFrequency(
cc::mojom::RootScrollOffsetUpdateFrequency::kOnScrollEnd);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
render_frame_metadata.root_scroll_offset = gfx::PointF(0.0f, 100.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
render_frame_metadata.root_scroll_offset->set_y(200.0f);
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.Times(0);
EXPECT_CALL(client(), OnRootScrollOffsetChanged(
*(render_frame_metadata.root_scroll_offset)))
.Times(0);
observer_impl().DidEndScroll();
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRootScrollOffsetChanged(
*(render_frame_metadata.root_scroll_offset)))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
}
TEST_F(RenderFrameMetadataObserverImplTest,
SendRenderFrameMetadataOnUpdateFrequency) {
ScopedCCTNewRFMPushBehaviorForTest feature(true);
const uint32_t expected_frame_token = 1337;
viz::CompositorFrameMetadata compositor_frame_metadata;
compositor_frame_metadata.send_frame_token_to_embedder = false;
compositor_frame_metadata.frame_token = expected_frame_token;
cc::RenderFrameMetadata render_frame_metadata;
observer_impl().OnRenderFrameSubmission(render_frame_metadata,
&compositor_frame_metadata,
false );
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
observer_impl().UpdateRootScrollOffsetUpdateFrequency(
cc::mojom::RootScrollOffsetUpdateFrequency::kNone);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
observer_impl().UpdateRootScrollOffsetUpdateFrequency(
cc::mojom::RootScrollOffsetUpdateFrequency::kOnScrollEnd);
{
base::RunLoop run_loop;
EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
render_frame_metadata))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
}
#endif
TEST_F(RenderFrameMetadataObserverImplTest, ForceSendMetadata) { … }
}