diff --git a/content/browser/renderer_host/cross_process_frame_connector.cc b/content/browser/renderer_host/cross_process_frame_connector.cc index 047e61a5329dd9..5e9f2324d35ffd 100644 --- a/content/browser/renderer_host/cross_process_frame_connector.cc +++ b/content/browser/renderer_host/cross_process_frame_connector.cc @@ -150,7 +150,10 @@ void CrossProcessFrameConnector::SendIntrinsicSizingInfoToParent( } void CrossProcessFrameConnector::SynchronizeVisualProperties( - const blink::FrameVisualProperties& visual_properties) { + const blink::FrameVisualProperties& visual_properties, + bool propagate) { + last_received_zoom_level_ = visual_properties.zoom_level; + last_received_local_frame_size_ = visual_properties.local_frame_size; screen_info_ = visual_properties.screen_info; local_surface_id_ = visual_properties.local_surface_id; @@ -176,7 +179,7 @@ void CrossProcessFrameConnector::SynchronizeVisualProperties( visual_properties.compositor_viewport, visual_properties.root_widget_window_segments); - render_widget_host->SynchronizeVisualProperties(); + render_widget_host->UpdateVisualProperties(propagate); } void CrossProcessFrameConnector::UpdateCursor(const WebCursor& cursor) { @@ -320,16 +323,25 @@ void CrossProcessFrameConnector::OnSynchronizeVisualProperties( return; } - last_received_zoom_level_ = visual_properties.zoom_level; - last_received_local_frame_size_ = visual_properties.local_frame_size; SynchronizeVisualProperties(visual_properties); } void CrossProcessFrameConnector::UpdateViewportIntersection( + const blink::mojom::ViewportIntersectionState& intersection_state, + const base::Optional& visual_properties) { + base::AutoReset(&is_processing_viewport_intersection_, true); + if (visual_properties.has_value()) + SynchronizeVisualProperties(visual_properties.value(), false); + UpdateViewportIntersectionInternal(intersection_state); +} + +void CrossProcessFrameConnector::UpdateViewportIntersectionInternal( const blink::mojom::ViewportIntersectionState& intersection_state) { intersection_state_ = intersection_state; - if (view_) - view_->UpdateViewportIntersection(intersection_state_); + if (view_) { + view_->UpdateViewportIntersection( + intersection_state_, view_->host()->LastComputedVisualProperties()); + } if (IsVisible()) { // Record metrics if a crashed subframe became visible as a result of this diff --git a/content/browser/renderer_host/cross_process_frame_connector.h b/content/browser/renderer_host/cross_process_frame_connector.h index adeb65ab45d481..e60c3229a8bce9 100644 --- a/content/browser/renderer_host/cross_process_frame_connector.h +++ b/content/browser/renderer_host/cross_process_frame_connector.h @@ -109,9 +109,11 @@ class CONTENT_EXPORT CrossProcessFrameConnector { // its corresponding remote frame in the parent frame's renderer. void SendIntrinsicSizingInfoToParent(blink::mojom::IntrinsicSizingInfoPtr); - // Sends new resize parameters to the subframe's renderer. + // Record and apply new visual properties for the subframe. If 'propagate' is + // true, the new properties will be sent to the subframe's renderer process. void SynchronizeVisualProperties( - const blink::FrameVisualProperties& visual_properties); + const blink::FrameVisualProperties& visual_properties, + bool propagate = true); // Return the size of the CompositorFrame to use in the child renderer. const gfx::Size& local_frame_size_in_pixels() const { @@ -283,7 +285,8 @@ class CONTENT_EXPORT CrossProcessFrameConnector { bool subtree_throttled, bool display_locked); void UpdateViewportIntersection( - const blink::mojom::ViewportIntersectionState& intersection_state); + const blink::mojom::ViewportIntersectionState& intersection_state, + const base::Optional& visual_properties); // These enums back crashed frame histograms - see MaybeLogCrash() and // MaybeLogShownCrash() below. Please do not modify or remove existing enum @@ -331,8 +334,17 @@ class CONTENT_EXPORT CrossProcessFrameConnector { use_zoom_for_device_scale_factor_ = use_zoom_for_device_scale_factor; } + // TODO(szager): This is a hack piled on top of a hack; see + // RenderWidgetHostViewChildFrame::WillSendScreenRects. We need a better way + // to initialize renderer process state after a frame migrates to a different + // process due to navigation. + bool IsProcessingViewportIntersection() const { + return is_processing_viewport_intersection_; + } + protected: friend class MockCrossProcessFrameConnector; + friend class SitePerProcessBrowserTestBase; FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewChildFrameZoomForDSFTest, CompositorViewportPixelSize); @@ -350,6 +362,9 @@ class CONTENT_EXPORT CrossProcessFrameConnector { // Stability.ChildFrameCrash.Visibility.ShownAfterCrashing* metrics. void MaybeLogShownCrash(ShownAfterCrashingReason reason); + void UpdateViewportIntersectionInternal( + const blink::mojom::ViewportIntersectionState& intersection_state); + // The RenderWidgetHostView for the frame. Initially nullptr. RenderWidgetHostViewChildFrame* view_ = nullptr; @@ -407,6 +422,9 @@ class CONTENT_EXPORT CrossProcessFrameConnector { // shown after a crash. This is only used when recording renderer crashes. bool delegate_was_shown_after_crash_ = false; + // This is used to prevent re-entry into UpdateViewportIntersection. + bool is_processing_viewport_intersection_ = false; + // The last pre-transform frame size received from the parent renderer. // |last_received_local_frame_size_| may be in DIP if use zoom for DSF is // off. diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index 24cc67b62327b8..0ce21b75f6c334 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc @@ -745,9 +745,10 @@ void RenderFrameProxyHost::OpenURL(mojom::OpenURLParamsPtr params) { } void RenderFrameProxyHost::UpdateViewportIntersection( - blink::mojom::ViewportIntersectionStatePtr intersection_state) { + blink::mojom::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) { cross_process_frame_connector_->UpdateViewportIntersection( - *intersection_state); + *intersection_state, visual_properties); } void RenderFrameProxyHost::DidChangeOpener( diff --git a/content/browser/renderer_host/render_frame_proxy_host.h b/content/browser/renderer_host/render_frame_proxy_host.h index eab125ad35fac3..844ddb791ff7ef 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.h +++ b/content/browser/renderer_host/render_frame_proxy_host.h @@ -184,7 +184,9 @@ class CONTENT_EXPORT RenderFrameProxyHost int document_cookie) override; void Detach() override; void UpdateViewportIntersection( - blink::mojom::ViewportIntersectionStatePtr intersection_state) override; + blink::mojom::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) + override; void SynchronizeVisualProperties( const blink::FrameVisualProperties& frame_visual_properties) override; diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index ace5178d559e89..92d88b6e059957 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1062,8 +1062,12 @@ blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() { return visual_properties; } +bool RenderWidgetHostImpl::UpdateVisualProperties(bool propagate) { + return SynchronizeVisualProperties(false, propagate); +} + bool RenderWidgetHostImpl::SynchronizeVisualProperties() { - return SynchronizeVisualProperties(false); + return SynchronizeVisualProperties(false, true); } bool RenderWidgetHostImpl::SynchronizeVisualPropertiesIgnoringPendingAck() { @@ -1072,7 +1076,8 @@ bool RenderWidgetHostImpl::SynchronizeVisualPropertiesIgnoringPendingAck() { } bool RenderWidgetHostImpl::SynchronizeVisualProperties( - bool scroll_focused_node_into_view) { + bool scroll_focused_node_into_view, + bool propagate) { // If the RenderViewHost is inactive, then there is no RenderWidget that can // receive visual properties yet, even though we are setting them on the // browser side. Wait until there is a local main frame with a RenderWidget @@ -1125,7 +1130,8 @@ bool RenderWidgetHostImpl::SynchronizeVisualProperties( visual_properties->scroll_focused_node_into_view = scroll_focused_node_into_view; - blink_widget_->UpdateVisualProperties(*visual_properties); + if (propagate) + blink_widget_->UpdateVisualProperties(*visual_properties); bool width_changed = !old_visual_properties_ || old_visual_properties_->new_size.width() != @@ -2939,7 +2945,7 @@ RenderWidgetHostImpl::GetFrameWidgetInputHandler() { } base::Optional -RenderWidgetHostImpl::GetLastVisualPropertiesSentToRendererForTesting() { +RenderWidgetHostImpl::LastComputedVisualProperties() const { if (!old_visual_properties_) return base::nullopt; return *old_visual_properties_; diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 8213f1f4f2f50e..42b1a91421d0e1 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -307,6 +307,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl void SetPopupBounds(const gfx::Rect& bounds, SetPopupBoundsCallback callback) override; + // Update the stored set of visual properties for the renderer. If 'propagate' + // is true, the new properties will be sent to the renderer process. + bool UpdateVisualProperties(bool propagate); + // Notification that the screen info has changed. void NotifyScreenInfoChanged(); @@ -665,7 +669,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl // Pushes updated visual properties to the renderer as well as whether the // focused node should be scrolled into view. - bool SynchronizeVisualProperties(bool scroll_focused_node_into_view); + bool SynchronizeVisualProperties(bool scroll_focused_node_into_view, + bool propagate = true); // Similar to SynchronizeVisualProperties(), but performed even if // |visual_properties_ack_pending_| is set. Used to guarantee that the @@ -823,6 +828,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl base::Optional GetLastVisualPropertiesSentToRendererForTesting(); + base::Optional LastComputedVisualProperties() const; + protected: // |routing_id| must not be MSG_ROUTING_NONE. // If this object outlives |delegate|, DetachDelegate() must be called when diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index ce37e22de466d4..66077de6f305ed 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc @@ -429,7 +429,8 @@ void RenderWidgetHostViewChildFrame::UnregisterFrameSinkId() { } void RenderWidgetHostViewChildFrame::UpdateViewportIntersection( - const blink::mojom::ViewportIntersectionState& intersection_state) { + const blink::mojom::ViewportIntersectionState& intersection_state, + const base::Optional& visual_properties) { if (host()) { host()->SetIntersectsViewport( !intersection_state.viewport_intersection.IsEmpty()); @@ -437,7 +438,7 @@ void RenderWidgetHostViewChildFrame::UpdateViewportIntersection( // Do not send viewport intersection to main frames. if (!host()->owner_delegate()) { host()->GetAssociatedFrameWidget()->SetViewportIntersection( - intersection_state.Clone()); + intersection_state.Clone(), visual_properties); } } } @@ -739,7 +740,10 @@ void RenderWidgetHostViewChildFrame::WillSendScreenRects() { // spammy way to do this, but triggering on SendScreenRects() is reasonable // until somebody figures that out. RWHVCF::Init() is too early. if (frame_connector_) { - UpdateViewportIntersection(frame_connector_->intersection_state()); + if (!frame_connector_->IsProcessingViewportIntersection()) { + UpdateViewportIntersection(frame_connector_->intersection_state(), + base::nullopt); + } SetIsInert(); UpdateInheritedEffectiveTouchAction(); UpdateRenderThrottlingStatus(); diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h index 9d782bbfa79f67..14626ec1af29ec 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.h +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h @@ -27,6 +27,7 @@ #include "content/common/content_export.h" #include "content/public/browser/touch_selection_controller_client_manager.h" #include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h" +#include "third_party/blink/public/common/widget/visual_properties.h" #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-forward.h" #include "third_party/blink/public/mojom/frame/viewport_intersection_state.mojom-forward.h" #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" @@ -181,7 +182,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame void UnregisterFrameSinkId(); void UpdateViewportIntersection( - const blink::mojom::ViewportIntersectionState& intersection_state); + const blink::mojom::ViewportIntersectionState& intersection_state, + const base::Optional& visual_properties); // TODO(sunxd): Rename SetIsInert to UpdateIsInert. void SetIsInert(); diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc index 16b1b072740172..9b17e6214d9a72 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc @@ -233,7 +233,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, // Wait to see the size sent to the child RenderWidget. while (true) { base::Optional properties = - child_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + child_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == initial_size) break; base::RunLoop().RunUntilIdle(); @@ -250,7 +250,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, // Wait to see the size sent to the child RenderWidget. while (true) { base::Optional properties = - nested_child_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + nested_child_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == nested_initial_size) break; @@ -279,14 +279,14 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, // Wait to see both RenderWidgets receive the message. while (true) { base::Optional properties = - root_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + root_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == resize_to) break; base::RunLoop().RunUntilIdle(); } while (true) { base::Optional properties = - child_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + child_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == resize_to) break; base::RunLoop().RunUntilIdle(); @@ -310,14 +310,14 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, // Wait to see both RenderWidgets receive the message. while (true) { base::Optional properties = - nested_root_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + nested_root_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == resize_to) break; base::RunLoop().RunUntilIdle(); } while (true) { base::Optional properties = - nested_child_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + nested_child_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == resize_to) break; base::RunLoop().RunUntilIdle(); @@ -350,14 +350,14 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, // waterfall to pass the new |visible_viewport_size| down. while (true) { base::Optional properties = - root_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + root_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == auto_resize_to) break; base::RunLoop().RunUntilIdle(); } while (true) { base::Optional properties = - child_rwh->GetLastVisualPropertiesSentToRendererForTesting(); + child_rwh->LastComputedVisualProperties(); if (properties && properties->visible_viewport_size == auto_resize_to) break; base::RunLoop().RunUntilIdle(); @@ -556,7 +556,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, base::Optional properties = oopchild->current_frame_host() ->GetRenderWidgetHost() - ->GetLastVisualPropertiesSentToRendererForTesting(); + ->LastComputedVisualProperties(); EXPECT_TRUE(properties); EXPECT_TRUE(properties->local_surface_id); viz::LocalSurfaceId oopchild_initial_lsid = @@ -564,7 +564,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, properties = oopdescendant->current_frame_host() ->GetRenderWidgetHost() - ->GetLastVisualPropertiesSentToRendererForTesting(); + ->LastComputedVisualProperties(); EXPECT_TRUE(properties); EXPECT_TRUE(properties->local_surface_id); viz::LocalSurfaceId oopdescendant_initial_lsid = @@ -583,7 +583,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, base::Optional properties = oopchild->current_frame_host() ->GetRenderWidgetHost() - ->GetLastVisualPropertiesSentToRendererForTesting(); + ->LastComputedVisualProperties(); if (properties && properties->local_surface_id && oopchild_initial_lsid < properties->local_surface_id) { EXPECT_EQ(properties->root_widget_window_segments, expected_segments); @@ -595,7 +595,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, base::Optional properties = oopdescendant->current_frame_host() ->GetRenderWidgetHost() - ->GetLastVisualPropertiesSentToRendererForTesting(); + ->LastComputedVisualProperties(); if (properties && properties->local_surface_id && oopdescendant_initial_lsid < properties->local_surface_id) { EXPECT_EQ(properties->root_widget_window_segments, expected_segments); @@ -617,7 +617,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, base::Optional properties = oopdescendant->current_frame_host() ->GetRenderWidgetHost() - ->GetLastVisualPropertiesSentToRendererForTesting(); + ->LastComputedVisualProperties(); // This check is needed, since we'll get an IPC originating from // RenderWidgetHostImpl immediately after the frame is added with the // incorrect value (the segments are cascaded from the parent renderer diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index fe24c5ce6b2065..7678e8e1cd2454 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc @@ -666,7 +666,9 @@ class UpdateViewportIntersectionMessageFilter } void UpdateViewportIntersection( - blink::mojom::ViewportIntersectionStatePtr intersection_state) override { + blink::mojom::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) + override { intersection_state_ = std::move(intersection_state); msg_received_ = true; if (run_loop_) @@ -733,6 +735,15 @@ void SitePerProcessBrowserTestBase::SetUpOnMainThread() { ASSERT_TRUE(embedded_test_server()->Start()); } +void SitePerProcessBrowserTestBase::ForceUpdateViewportIntersection( + FrameTreeNode* frame_tree_node, + const blink::mojom::ViewportIntersectionState& intersection_state) { + frame_tree_node->render_manager() + ->GetProxyToParent() + ->cross_process_frame_connector() + ->UpdateViewportIntersectionInternal(intersection_state); +} + // // SitePerProcessBrowserTest // @@ -13272,7 +13283,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, while (true) { auto* rwh_b = child_b->current_frame_host()->GetRenderWidgetHost(); base::Optional properties = - rwh_b->GetLastVisualPropertiesSentToRendererForTesting(); + rwh_b->LastComputedVisualProperties(); if (properties && cc::MathUtil::IsFloatNearlyTheSame( properties->compositing_scale_factor, 0.5f)) { break; @@ -13288,7 +13299,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, while (true) { auto* rwh_c = child_c->current_frame_host()->GetRenderWidgetHost(); base::Optional properties = - rwh_c->GetLastVisualPropertiesSentToRendererForTesting(); + rwh_c->LastComputedVisualProperties(); if (properties && cc::MathUtil::IsFloatNearlyTheSame( properties->compositing_scale_factor, 0.5f)) { break; @@ -13303,7 +13314,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, while (true) { auto* rwh_d = child_d->current_frame_host()->GetRenderWidgetHost(); base::Optional properties = - rwh_d->GetLastVisualPropertiesSentToRendererForTesting(); + rwh_d->LastComputedVisualProperties(); if (properties && cc::MathUtil::IsFloatNearlyTheSame( properties->compositing_scale_factor, 0.25f)) { break; @@ -13343,7 +13354,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, while (true) { auto* rwh_b = child_b->current_frame_host()->GetRenderWidgetHost(); base::Optional properties = - rwh_b->GetLastVisualPropertiesSentToRendererForTesting(); + rwh_b->LastComputedVisualProperties(); if (properties && cc::MathUtil::IsFloatNearlyTheSame( properties->compositing_scale_factor, 0.5f)) { break; @@ -13362,7 +13373,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, while (true) { auto* rwh_b = child_b->current_frame_host()->GetRenderWidgetHost(); base::Optional properties = - rwh_b->GetLastVisualPropertiesSentToRendererForTesting(); + rwh_b->LastComputedVisualProperties(); if (properties && !cc::MathUtil::IsFloatNearlyTheSame( properties->compositing_scale_factor, 0.5f)) { EXPECT_GT(properties->compositing_scale_factor, 0.0f); @@ -16464,10 +16475,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, MainFrameScrollOffset) { b1_intersection_state.viewport_intersection.set_height( b1_intersection_state.viewport_intersection.height() - 7); - b1_node->render_manager() - ->GetProxyToParent() - ->cross_process_frame_connector() - ->UpdateViewportIntersection(b1_intersection_state); + ForceUpdateViewportIntersection(b1_node, b1_intersection_state); auto b2_intersection_state = b2_node->render_manager() ->GetProxyToParent() @@ -16480,10 +16488,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, MainFrameScrollOffset) { b2_intersection_state.viewport_intersection.set_height( b2_intersection_state.viewport_intersection.height() - 7); - b2_node->render_manager() - ->GetProxyToParent() - ->cross_process_frame_connector() - ->UpdateViewportIntersection(b2_intersection_state); + ForceUpdateViewportIntersection(b2_node, b2_intersection_state); // Once IPC's have been flushed to the C frames, we should see conflicting // values for main_frame_scroll_offset. diff --git a/content/browser/site_per_process_browsertest.h b/content/browser/site_per_process_browsertest.h index 171c98b1397030..ba34258816b4f4 100644 --- a/content/browser/site_per_process_browsertest.h +++ b/content/browser/site_per_process_browsertest.h @@ -33,6 +33,10 @@ class SitePerProcessBrowserTestBase : public ContentBrowserTest { return static_cast(shell()->web_contents()); } + static void ForceUpdateViewportIntersection( + FrameTreeNode* frame_tree_node, + const blink::mojom::ViewportIntersectionState& intersection_state); + private: FrameTreeVisualizer visualizer_; base::test::ScopedFeatureList feature_list_; diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h index b52c0805947d0d..8e6e3519059075 100644 --- a/content/public/browser/render_widget_host.h +++ b/content/public/browser/render_widget_host.h @@ -219,7 +219,7 @@ class CONTENT_EXPORT RenderWidgetHost { virtual bool IsCurrentlyUnresponsive() = 0; // Called to propagate updated visual properties to the renderer. Returns - // whether the renderer has been informed of updated properties. + // true if visual properties have changed since last call. virtual bool SynchronizeVisualProperties() = 0; // Access to the implementation's IPC::Listener::OnMessageReceived. Intended diff --git a/content/public/test/fake_frame_widget.cc b/content/public/test/fake_frame_widget.cc index 2bc8c1af535c35..4c30d1ab4926e0 100644 --- a/content/public/test/fake_frame_widget.cc +++ b/content/public/test/fake_frame_widget.cc @@ -42,7 +42,8 @@ FakeFrameWidget::GetIntersectionState() const { } void FakeFrameWidget::SetViewportIntersection( - blink::mojom::ViewportIntersectionStatePtr intersection_state) { + blink::mojom::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) { intersection_state_ = std::move(intersection_state); } diff --git a/content/public/test/fake_frame_widget.h b/content/public/test/fake_frame_widget.h index 65ca492f0e5ba1..bdf92d6c9c188a 100644 --- a/content/public/test/fake_frame_widget.h +++ b/content/public/test/fake_frame_widget.h @@ -82,7 +82,9 @@ class FakeFrameWidget : public blink::mojom::FrameWidget { void BindInputTargetClient( mojo::PendingReceiver receiver) override {} void SetViewportIntersection( - blink::mojom::ViewportIntersectionStatePtr intersection_state) override; + blink::mojom::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) + override; mojo::AssociatedReceiver receiver_; base::i18n::TextDirection text_direction_ = diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index ae80513384c6f5..f6c9abc163c6db 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom @@ -780,7 +780,8 @@ interface RemoteFrameHost { // intersection with the parent's viewport, primarily for use by the // IntersectionObserver API. UpdateViewportIntersection( - ViewportIntersectionState intersection_state); + ViewportIntersectionState intersection_state, + FrameVisualProperties? visual_properties); // Tells the browser that a child's visual properties have changed. SynchronizeVisualProperties( diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom index aca77842a29e6c..12214f6e80f824 100644 --- a/third_party/blink/public/mojom/page/widget.mojom +++ b/third_party/blink/public/mojom/page/widget.mojom @@ -138,7 +138,8 @@ interface FrameWidget { // intersection with the parent's viewport, primarily for use by the // IntersectionObserver API. Also see 'UpdateViewportIntersection' in // third_party/blink/public/mojom/frame/viewport_intersection_state.mojom - SetViewportIntersection(ViewportIntersectionState intersection_state); + SetViewportIntersection(ViewportIntersectionState intersection_state, + VisualProperties? visual_properties); }; // Implemented in Browser, this interface defines frame-widget-specific methods that diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index 55acd41ba13b04..48d1aaafd55240 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc @@ -748,11 +748,12 @@ void TestWebRemoteFrameClient::FrameDetached(DetachType type) { } viz::FrameSinkId TestWebRemoteFrameClient::GetFrameSinkId() const { - return viz::FrameSinkId(); + return viz::FrameSinkId(1u, 1u); } const viz::LocalSurfaceId& TestWebRemoteFrameClient::GetLocalSurfaceId() const { - DEFINE_STATIC_LOCAL(viz::LocalSurfaceId, dummy_local_surface_id, ()); + DEFINE_STATIC_LOCAL(viz::LocalSurfaceId, dummy_local_surface_id, + (1u, base::UnguessableToken::Create())); return dummy_local_surface_id; } diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index cf47ceddb71f51..a5c9eec61ebf5a 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc @@ -845,9 +845,9 @@ void RemoteFrame::ApplyReplicatedFeaturePolicyHeader() { feature_policy_header_, container_policy, parent_feature_policy); } -void RemoteFrame::SynchronizeVisualProperties() { +bool RemoteFrame::SynchronizeVisualProperties(bool propagate) { if (!GetFrameSinkId().is_valid() || Client()->RemoteProcessGone()) - return; + return false; bool capture_sequence_number_changed = sent_visual_properties_ && @@ -903,14 +903,19 @@ void RemoteFrame::SynchronizeVisualProperties() { bool visual_properties_changed = synchronized_props_changed || rect_changed; if (!visual_properties_changed) - return; + return false; - // Let the browser know about the updated view rect. - GetRemoteFrameHostRemote().SynchronizeVisualProperties( - pending_visual_properties_); + if (propagate) { + GetRemoteFrameHostRemote().SynchronizeVisualProperties( + pending_visual_properties_); + RecordSentVisualProperties(); + } - sent_visual_properties_ = pending_visual_properties_; + return true; +} +void RemoteFrame::RecordSentVisualProperties() { + sent_visual_properties_ = pending_visual_properties_; TRACE_EVENT_WITH_FLOW2( TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), "RenderFrameProxy::SynchronizeVisualProperties Send Message", @@ -926,6 +931,17 @@ void RemoteFrame::ResendVisualProperties() { SynchronizeVisualProperties(); } +void RemoteFrame::SetViewportIntersection( + const mojom::blink::ViewportIntersectionState& intersection_state) { + base::Optional visual_properties; + if (SynchronizeVisualProperties(/*propagate=*/false)) { + visual_properties.emplace(pending_visual_properties_); + RecordSentVisualProperties(); + } + GetRemoteFrameHostRemote().UpdateViewportIntersection( + intersection_state.Clone(), visual_properties); +} + void RemoteFrame::DidChangeScreenInfo(const ScreenInfo& screen_info) { pending_visual_properties_.screen_info = screen_info; SynchronizeVisualProperties(); diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index 88e8dbaea4cf48..125ed205402816 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h @@ -116,8 +116,11 @@ class CORE_EXPORT RemoteFrame final : public Frame, void FrameRectsChanged(const IntRect& local_frame_rect, const IntRect& screen_space_rect); void InitializeFrameVisualProperties(const FrameVisualProperties& properties); - void SynchronizeVisualProperties(); + // If 'propagate' is true, updated properties will be sent to the browser. + // Returns true if visual properties have changed. + bool SynchronizeVisualProperties(bool propagate = true); void ResendVisualProperties(); + void SetViewportIntersection(const mojom::blink::ViewportIntersectionState&); // Called when the local root's screen info changes. void DidChangeScreenInfo(const ScreenInfo& screen_info); @@ -228,6 +231,7 @@ class CORE_EXPORT RemoteFrame final : public Frame, // Returns false if detaching child frames reentrantly detached `this`. bool DetachChildren(); void ApplyReplicatedFeaturePolicyHeader(); + void RecordSentVisualProperties(); static void BindToReceiver( RemoteFrame* frame, diff --git a/third_party/blink/renderer/core/frame/remote_frame_view.cc b/third_party/blink/renderer/core/frame/remote_frame_view.cc index cdc9da7c118d9c..5a7b5b5ebd1497 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_view.cc +++ b/third_party/blink/renderer/core/frame/remote_frame_view.cc @@ -107,8 +107,7 @@ void RemoteFrameView::SetViewportIntersection( if (!last_intersection_state_.Equals(new_state)) { last_intersection_state_ = new_state; GetFrame().SynchronizeVisualProperties(); - remote_frame_->GetRemoteFrameHostRemote().UpdateViewportIntersection( - new_state.Clone()); + remote_frame_->SetViewportIntersection(new_state); } else if (needs_frame_rect_propagation_) { PropagateFrameRects(); } diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 4493e3383316a1..681a77dec97b91 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc @@ -7298,7 +7298,7 @@ TEST_F(WebFrameTest, MainFrameIntersectionChanged) { auto intersection_state = blink::mojom::blink::ViewportIntersectionState::New( viewport_intersection, mainframe_intersection, gfx::Rect(), occlusion_state, gfx::Size(), gfx::Point(), transform); - static_cast(widget)->SetViewportIntersection( + static_cast(widget)->ApplyViewportIntersectionForTesting( std::move(intersection_state)); EXPECT_EQ(client.MainFrameIntersection(), blink::WebRect(100, 100, 200, 140)); } @@ -10664,7 +10664,8 @@ class TestViewportIntersection : public FakeRemoteFrameHost { // FakeRemoteFrameHost: void UpdateViewportIntersection( - mojom::blink::ViewportIntersectionStatePtr intersection_state) override { + mojom::blink::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) override { intersection_state_ = std::move(intersection_state); } @@ -13516,7 +13517,7 @@ TEST_F(WebFrameTest, RemoteViewportAndMainframeIntersections) { blink::mojom::FrameOcclusionState occlusion_state = blink::mojom::FrameOcclusionState::kUnknown; - static_cast(widget)->SetViewportIntersection( + static_cast(widget)->ApplyViewportIntersectionForTesting( blink::mojom::blink::ViewportIntersectionState::New( viewport_intersection, mainframe_intersection, viewport_intersection, occlusion_state, gfx::Size(), gfx::Point(), viewport_transform)); diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 74a701be566a8f..51c5630f6a9c42 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc @@ -1716,11 +1716,24 @@ void WebFrameWidgetImpl::ShowContextMenu( } void WebFrameWidgetImpl::SetViewportIntersection( - mojom::blink::ViewportIntersectionStatePtr intersection_state) { + mojom::blink::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) { // Remote viewports are only applicable to local frames with remote ancestors. // TODO(https://crbug.com/1148960): Should this deal with portals? DCHECK(ForSubframe()); + if (visual_properties.has_value()) + UpdateVisualProperties(visual_properties.value()); + ApplyViewportIntersection(std::move(intersection_state)); +} + +void WebFrameWidgetImpl::ApplyViewportIntersectionForTesting( + mojom::blink::ViewportIntersectionStatePtr intersection_state) { + ApplyViewportIntersection(std::move(intersection_state)); +} + +void WebFrameWidgetImpl::ApplyViewportIntersection( + mojom::blink::ViewportIntersectionStatePtr intersection_state) { child_data().compositor_visible_rect = intersection_state->compositor_visible_rect; widget_base_->LayerTreeHost()->SetVisualDeviceViewportIntersectionRect( diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index c1316d71aa642d..210f7640483397 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h @@ -289,6 +289,8 @@ class CORE_EXPORT WebFrameWidgetImpl bool ScrollFocusedEditableElementIntoView() override; void ApplyViewportChangesForTesting( const ApplyViewportChangesArgs& args) override; + void ApplyViewportIntersectionForTesting( + mojom::blink::ViewportIntersectionStatePtr intersection_state); void NotifySwapAndPresentationTime( WebReportTimeCallback swap_callback, WebReportTimeCallback presentation_callback) override; @@ -375,7 +377,8 @@ class CORE_EXPORT WebFrameWidgetImpl void ShowContextMenu(ui::mojom::MenuSourceType source_type, const gfx::Point& location) override; void SetViewportIntersection( - mojom::blink::ViewportIntersectionStatePtr intersection_state) override; + mojom::blink::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) override; void DragSourceEndedAt(const gfx::PointF& point_in_viewport, const gfx::PointF& screen_point, ui::mojom::blink::DragOperation) override; @@ -804,6 +807,9 @@ class CORE_EXPORT WebFrameWidgetImpl const gfx::Size& max_size_before_dsf, float device_scale_factor); + void ApplyViewportIntersection( + mojom::blink::ViewportIntersectionStatePtr intersection_state); + // Called when a gesture event has been processed. void DidHandleGestureEvent(const WebGestureEvent& event); diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc index aa684e3e58bd83..4f2f4bb3c65765 100644 --- a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc @@ -1719,7 +1719,7 @@ TEST_P(FrameThrottlingTest, NestedFramesInRemoteFrameHiddenAndShown) { intersection.viewport_intersection = gfx::Rect(0, 0, 100, 100); LocalFrameRoot().FrameWidget()->Resize(gfx::Size(300, 200)); static_cast(LocalFrameRoot().FrameWidget()) - ->SetViewportIntersection(intersection.Clone()); + ->ApplyViewportIntersectionForTesting(intersection.Clone()); auto* root_frame = LocalFrameRoot().GetFrame(); auto* frame_document = @@ -1760,7 +1760,7 @@ TEST_P(FrameThrottlingTest, NestedFramesInRemoteFrameHiddenAndShown) { // Show the frame without any other change. LocalFrameRoot().WasShown(); static_cast(LocalFrameRoot().FrameWidget()) - ->SetViewportIntersection(intersection.Clone()); + ->ApplyViewportIntersectionForTesting(intersection.Clone()); CompositeFrame(); EXPECT_EQ(root_frame->RemoteViewportIntersection(), IntRect(0, 0, 100, 100)); EXPECT_FALSE(root_frame->View()->CanThrottleRenderingForPropagation()); diff --git a/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc b/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc index 50a7d2d88b5f35..59d23ccfaf35f5 100644 --- a/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_remote_frame_host.cc @@ -52,7 +52,8 @@ void FakeRemoteFrameHost::PrintCrossProcessSubframe(const gfx::Rect& rect, void FakeRemoteFrameHost::Detach() {} void FakeRemoteFrameHost::UpdateViewportIntersection( - blink::mojom::blink::ViewportIntersectionStatePtr intersection_state) {} + blink::mojom::blink::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) {} void FakeRemoteFrameHost::SynchronizeVisualProperties( const blink::FrameVisualProperties& properties) {} diff --git a/third_party/blink/renderer/core/testing/fake_remote_frame_host.h b/third_party/blink/renderer/core/testing/fake_remote_frame_host.h index dd3b73351f45e0..6f23b445c5e0ec 100644 --- a/third_party/blink/renderer/core/testing/fake_remote_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_remote_frame_host.h @@ -49,8 +49,8 @@ class FakeRemoteFrameHost : public mojom::blink::RemoteFrameHost { int document_cookie) override; void Detach() override; void UpdateViewportIntersection( - blink::mojom::blink::ViewportIntersectionStatePtr intersection_state) - override; + blink::mojom::blink::ViewportIntersectionStatePtr intersection_state, + const base::Optional& visual_properties) override; void SynchronizeVisualProperties( const blink::FrameVisualProperties& properties) override;