Skip to content

Commit

Permalink
Reland "Don't PostTask the RenderWidget::Close() call."
Browse files Browse the repository at this point in the history
This is a reland of 8f0dc96

Original change's description:
> Don't PostTask the RenderWidget::Close() call.
>
> The post task in RenderWidget was in order to keep IPC receipt of
> destruction of a frame-based RenderWidget (ie a RenderView in the past)
> from happening while the RenderWidget was already closing due to the
> renderer-side detaching, but running a nested message loop.
>
> The RenderView destruction now already does a PostTask hop in
> RenderThreadImpl before starting destruction of the RenderViewImpl
> and its frame tree and RenderWidgets. A RenderWidget for a frame closes
> when the frame detaches, and that is built to be consistent even if
> it occurs inside of unload. The RenderWidget does not need to be kept
> around after the blink frame and RenderFrame and WebWidget associated
> with it are all gone.
>
> Popups and pepper RenderWidgets can close during a frame unload without
> a consistency problem.
>
> R=dcheng@chromium.org
>
> Bug: 419087
> Change-Id: Ia5f7ca07395f8a5bd2c60a974a0fb4fb5092d872
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1832612
> Reviewed-by: Avi Drissman <avi@chromium.org>
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> Commit-Queue: danakj <danakj@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#702868}

TBR=dcheng

Bug: 419087
Change-Id: I0f68df454e2873d7e6f3eeb38ff41563c16f6a76
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1841942
Reviewed-by: Avi Drissman <avi@chromium.org>
Commit-Queue: danakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702977}
  • Loading branch information
danakj authored and Commit Bot committed Oct 4, 2019
1 parent e44132f commit f24dc81
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 160 deletions.
2 changes: 2 additions & 0 deletions content/renderer/compositor/compositor_dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class CONTENT_EXPORT CompositorDependencies {
// compositor thread).
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetCompositorImplThreadTaskRunner() = 0;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetCleanupTaskRunner() = 0;
virtual blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() = 0;
virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
virtual bool IsScrollAnimatorEnabled() = 0;
Expand Down
65 changes: 62 additions & 3 deletions content/renderer/compositor/layer_tree_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,19 @@ LayerTreeView::LayerTreeView(
scoped_refptr<base::SingleThreadTaskRunner> compositor_thread,
cc::TaskGraphRunner* task_graph_runner,
blink::scheduler::WebThreadScheduler* scheduler)
: delegate_(delegate),
main_thread_(std::move(main_thread)),
: main_thread_(std::move(main_thread)),
compositor_thread_(std::move(compositor_thread)),
task_graph_runner_(task_graph_runner),
web_main_thread_scheduler_(scheduler),
animation_host_(cc::AnimationHost::CreateMainInstance()) {}
animation_host_(cc::AnimationHost::CreateMainInstance()),
delegate_(delegate) {}

LayerTreeView::~LayerTreeView() = default;

void LayerTreeView::Initialize(
const cc::LayerTreeSettings& settings,
std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) {
DCHECK(delegate_);
const bool is_threaded = !!compositor_thread_;

cc::LayerTreeHost::InitParams params;
Expand Down Expand Up @@ -99,7 +100,17 @@ void LayerTreeView::Initialize(
}
}

void LayerTreeView::Disconnect() {
DCHECK(delegate_);
// Drop compositor resources immediately, while keeping the compositor alive
// until after this class is destroyed.
layer_tree_host_->SetVisible(false);
layer_tree_host_->ReleaseLayerTreeFrameSink();
delegate_ = nullptr;
}

void LayerTreeView::SetVisible(bool visible) {
DCHECK(delegate_);
layer_tree_host_->SetVisible(visible);

if (visible && layer_tree_frame_sink_request_failed_while_invisible_)
Expand All @@ -108,6 +119,7 @@ void LayerTreeView::SetVisible(bool visible) {

void LayerTreeView::SetLayerTreeFrameSink(
std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink) {
DCHECK(delegate_);
if (!layer_tree_frame_sink) {
DidFailToInitializeLayerTreeFrameSink();
return;
Expand All @@ -116,18 +128,26 @@ void LayerTreeView::SetLayerTreeFrameSink(
}

void LayerTreeView::WillBeginMainFrame() {
if (!delegate_)
return;
delegate_->WillBeginCompositorFrame();
}

void LayerTreeView::DidBeginMainFrame() {
if (!delegate_)
return;
delegate_->DidBeginMainFrame();
}

void LayerTreeView::WillUpdateLayers() {
if (!delegate_)
return;
delegate_->BeginUpdateLayers();
}

void LayerTreeView::DidUpdateLayers() {
if (!delegate_)
return;
delegate_->EndUpdateLayers();
// Dump property trees and layers if run with:
// --vmodule=layer_tree_view=3
Expand All @@ -139,52 +159,74 @@ void LayerTreeView::DidUpdateLayers() {
}

void LayerTreeView::BeginMainFrame(const viz::BeginFrameArgs& args) {
if (!delegate_)
return;
web_main_thread_scheduler_->WillBeginFrame(args);
delegate_->BeginMainFrame(args.frame_time);
}

void LayerTreeView::OnDeferMainFrameUpdatesChanged(bool status) {
if (!delegate_)
return;
delegate_->OnDeferMainFrameUpdatesChanged(status);
}

void LayerTreeView::OnDeferCommitsChanged(bool status) {
if (!delegate_)
return;
delegate_->OnDeferCommitsChanged(status);
}

void LayerTreeView::BeginMainFrameNotExpectedSoon() {
if (!delegate_)
return;
web_main_thread_scheduler_->BeginFrameNotExpectedSoon();
}

void LayerTreeView::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {
if (!delegate_)
return;
web_main_thread_scheduler_->BeginMainFrameNotExpectedUntil(time);
}

void LayerTreeView::UpdateLayerTreeHost() {
if (!delegate_)
return;
delegate_->UpdateVisualState();
}

void LayerTreeView::ApplyViewportChanges(
const cc::ApplyViewportChangesArgs& args) {
if (!delegate_)
return;
delegate_->ApplyViewportChanges(args);
}

void LayerTreeView::RecordManipulationTypeCounts(cc::ManipulationInfo info) {
if (!delegate_)
return;
delegate_->RecordManipulationTypeCounts(info);
}

void LayerTreeView::SendOverscrollEventFromImplSide(
const gfx::Vector2dF& overscroll_delta,
cc::ElementId scroll_latched_element_id) {
if (!delegate_)
return;
delegate_->SendOverscrollEventFromImplSide(overscroll_delta,
scroll_latched_element_id);
}

void LayerTreeView::SendScrollEndEventFromImplSide(
cc::ElementId scroll_latched_element_id) {
if (!delegate_)
return;
delegate_->SendScrollEndEventFromImplSide(scroll_latched_element_id);
}

void LayerTreeView::RequestNewLayerTreeFrameSink() {
if (!delegate_)
return;
// When the compositor is not visible it would not request a
// LayerTreeFrameSink so this is a race where it requested one then became
// not-visible. In that case, we can wait for it to become visible again
Expand Down Expand Up @@ -217,6 +259,8 @@ void LayerTreeView::RequestNewLayerTreeFrameSink() {
void LayerTreeView::DidInitializeLayerTreeFrameSink() {}

void LayerTreeView::DidFailToInitializeLayerTreeFrameSink() {
if (!delegate_)
return;
if (!layer_tree_host_->IsVisible()) {
layer_tree_frame_sink_request_failed_while_invisible_ = true;
return;
Expand All @@ -228,25 +272,35 @@ void LayerTreeView::DidFailToInitializeLayerTreeFrameSink() {
}

void LayerTreeView::WillCommit() {
if (!delegate_)
return;
delegate_->WillCommitCompositorFrame();
}

void LayerTreeView::DidCommit() {
if (!delegate_)
return;
delegate_->DidCommitCompositorFrame();
web_main_thread_scheduler_->DidCommitFrameToCompositor();
}

void LayerTreeView::DidCommitAndDrawFrame() {
if (!delegate_)
return;
delegate_->DidCommitAndDrawCompositorFrame();
}

void LayerTreeView::DidCompletePageScaleAnimation() {
if (!delegate_)
return;
delegate_->DidCompletePageScaleAnimation();
}

void LayerTreeView::DidPresentCompositorFrame(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) {
if (!delegate_)
return;
DCHECK(layer_tree_host_->GetTaskRunnerProvider()
->MainThreadTaskRunner()
->RunsTasksInCurrentSequence());
Expand All @@ -261,10 +315,14 @@ void LayerTreeView::DidPresentCompositorFrame(
}

void LayerTreeView::RecordStartOfFrameMetrics() {
if (!delegate_)
return;
delegate_->RecordStartOfFrameMetrics();
}

void LayerTreeView::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) {
if (!delegate_)
return;
delegate_->RecordEndOfFrameMetrics(frame_begin_time);
}

Expand All @@ -288,6 +346,7 @@ void LayerTreeView::DidLoseLayerTreeFrameSink() {}
void LayerTreeView::AddPresentationCallback(
uint32_t frame_token,
base::OnceCallback<void(base::TimeTicks)> callback) {
DCHECK(delegate_);
if (!presentation_callbacks_.empty()) {
auto& previous = presentation_callbacks_.back();
uint32_t previous_frame_token = previous.first;
Expand Down
13 changes: 12 additions & 1 deletion content/renderer/compositor/layer_tree_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class CONTENT_EXPORT LayerTreeView : public cc::LayerTreeHostClient,
void Initialize(const cc::LayerTreeSettings& settings,
std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory);

// Drops any references back to the delegate in preparation for being
// destroyed.
void Disconnect();

cc::AnimationHost* animation_host() { return animation_host_.get(); }

void SetVisible(bool visible);
Expand Down Expand Up @@ -121,14 +125,21 @@ class CONTENT_EXPORT LayerTreeView : public cc::LayerTreeHostClient,
void SetLayerTreeFrameSink(
std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink);

LayerTreeViewDelegate* const delegate_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
const scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_;
cc::TaskGraphRunner* const task_graph_runner_;
blink::scheduler::WebThreadScheduler* const web_main_thread_scheduler_;
const std::unique_ptr<cc::AnimationHost> animation_host_;

// The delegate_ becomes null when Disconnect() is called. After that, the
// class should do nothing in calls from the LayerTreeHost, and just wait to
// be destroyed. It is not expected to be used at all after Disconnect()
// outside of handling/dropping LayerTreeHost client calls.
LayerTreeViewDelegate* delegate_;
std::unique_ptr<cc::LayerTreeHost> layer_tree_host_;

// This class should do nothing and access no pointers once this value becomes
// true.
bool layer_tree_frame_sink_request_failed_while_invisible_ = false;

base::circular_deque<
Expand Down
3 changes: 1 addition & 2 deletions content/renderer/input/widget_input_handler_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ void RunClosureIfNotSwappedOut(base::WeakPtr<RenderWidget> render_widget,
base::OnceClosure closure) {
// Input messages must not be processed if the RenderWidget was undead or is
// closing.
if (!render_widget || render_widget->IsUndeadOrProvisional() ||
render_widget->is_closing()) {
if (!render_widget || render_widget->IsUndeadOrProvisional()) {
return;
}
std::move(closure).Run();
Expand Down
3 changes: 1 addition & 2 deletions content/renderer/input/widget_input_handler_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,7 @@ void WidgetInputHandlerManager::HandleInputEvent(
const ui::WebScopedInputEvent& event,
const ui::LatencyInfo& latency,
mojom::WidgetInputHandler::DispatchEventCallback callback) {
if (!render_widget_ || render_widget_->IsUndeadOrProvisional() ||
render_widget_->is_closing()) {
if (!render_widget_ || render_widget_->IsUndeadOrProvisional()) {
if (callback) {
std::move(callback).Run(InputEventAckSource::MAIN_THREAD, latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED, base::nullopt,
Expand Down
7 changes: 7 additions & 0 deletions content/renderer/render_thread_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,13 @@ RenderThreadImpl::GetCompositorImplThreadTaskRunner() {
return compositor_task_runner_;
}

scoped_refptr<base::SingleThreadTaskRunner>
RenderThreadImpl::GetCleanupTaskRunner() {
return current_blink_platform_impl()
->main_thread_scheduler()
->CleanupTaskRunner();
}

gpu::GpuMemoryBufferManager* RenderThreadImpl::GetGpuMemoryBufferManager() {
return gpu_->gpu_memory_buffer_manager();
}
Expand Down
1 change: 1 addition & 0 deletions content/renderer/render_thread_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class CONTENT_EXPORT RenderThreadImpl
GetCompositorMainThreadTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner>
GetCompositorImplThreadTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> GetCleanupTaskRunner() override;
blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() override;
cc::TaskGraphRunner* GetTaskGraphRunner() override;
bool IsScrollAnimatorEnabled() override;
Expand Down
16 changes: 4 additions & 12 deletions content/renderer/render_view_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1072,16 +1072,12 @@ void RenderViewImpl::Destroy() {
// a main frame. So it should not be able to see this happening when there is
// no local main frame.
if (close_render_widget_here) {
// TODO(danakj): Go through CloseForFrame()? But we don't need/want to post-
// task the Close step here, do we? Since we're inside RenderViewImpl
// destruction?
render_widget_->PrepareForClose();
// We pass ownership of |render_widget_| to itself. Grab a raw pointer to
// call the Close() method on so we don't have to be a C++ expert to know
// whether we will end up with a nullptr where we didn't intend due to order
// of execution.
RenderWidget* closing_widget = render_widget_.get();
closing_widget->Close(std::move(render_widget_));
closing_widget->CloseForFrame(std::move(render_widget_));
}

delete this;
Expand Down Expand Up @@ -1571,19 +1567,15 @@ void RenderViewImpl::DetachWebFrameWidget() {
// We are inside RenderViewImpl::Destroy() and the main frame is being
// detached as part of shutdown. So we can destroy the RenderWidget.

// The RenderWidget is closed and it will close the WebWidget stored in
// |frame_widget_|. We just want to drop raw pointer here.
// The RenderWidget will be closed, and it will close the WebWidget stored
// in |frame_widget_|. We just want to drop raw pointer here.
frame_widget_ = nullptr;
// TODO(danakj): Go through CloseForFrame()? But we don't need/want to post-
// task the Close step here, do we? Since we're inside RenderViewImpl
// destruction?
render_widget_->PrepareForClose();
// We pass ownership of |render_widget_| to itself. Grab a raw pointer to
// call the Close() method on so we don't have to be a C++ expert to know
// whether we will end up with a nullptr where we didn't intend due to order
// of execution.
RenderWidget* closing_widget = render_widget_.get();
closing_widget->Close(std::move(render_widget_));
closing_widget->CloseForFrame(std::move(render_widget_));
} else {
// We are not inside RenderViewImpl::Destroy(), the main frame is being
// detached and replaced with a remote frame proxy. We can't close the
Expand Down
Loading

0 comments on commit f24dc81

Please sign in to comment.