Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1222)

Unified Diff: content/browser/renderer_host/render_view_host_impl.cc

Issue 213413005: Ensure RenderViewHost is not shut down until a screenshot of the page is taken. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Implementing review feedback. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/renderer_host/render_view_host_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/renderer_host/render_view_host_impl.cc
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index e942a281cffce1162c11f819581336d49e3e70a1..d371542edcaa734ac6a8e6eee9d427ad66de5a7c 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -214,6 +214,8 @@ RenderViewHostImpl::RenderViewHostImpl(
sudden_termination_allowed_(false),
render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
virtual_keyboard_requested_(false),
+ pending_shutdown_on_copy_requests_done_(false),
+ copy_requests_(0),
weak_factory_(this) {
DCHECK(instance_.get());
CHECK(delegate_); // http://crbug.com/82827
@@ -258,6 +260,12 @@ RenderViewHostImpl::~RenderViewHostImpl() {
CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
GetProcess()->GetID(), GetRoutingID(), false);
+ // The host shouldn't be destroyed when there is an outstanding copy request,
+ // otherwise the underlying layer would be destroyed underneath the copy
+ // request before it has a chance to complete.
+ // crbug.com/340682
+ DCHECK(copy_requests_ == 0);
+
// If this was swapped out, it already decremented the active view
// count of the SiteInstance it belongs to.
if (IsRVHStateActive(rvh_state_))
@@ -647,7 +655,10 @@ void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
break;
case STATE_PENDING_SHUTDOWN:
DCHECK(!pending_shutdown_on_swap_out_.is_null());
- pending_shutdown_on_swap_out_.Run();
+ if (copy_requests_ == 0)
+ pending_shutdown_on_swap_out_.Run();
+ else
+ pending_shutdown_on_copy_requests_done_ = true;
break;
default:
NOTREACHED();
@@ -656,13 +667,28 @@ void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
void RenderViewHostImpl::WasSwappedOut(
const base::Closure& pending_delete_on_swap_out) {
- Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
+ // Sending the ViewMsg_WasSwappedOut message would result in
+ // ChildProcessHostMsg_ShutdownRequest, which would lead to the destruction of
+ // the host and the cc layer. If there is an outstanding copy request, delay
+ // sending this message until it completes (see CopyFromBackingStoreCallback).
+ // crbug.com/340682
+ if (copy_requests_ == 0)
+ Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
if (rvh_state_ == STATE_WAITING_FOR_UNLOAD_ACK) {
SetState(STATE_PENDING_SWAP_OUT);
- if (!instance_->active_view_count())
+ if (!instance_->active_view_count()) {
SetPendingShutdown(pending_delete_on_swap_out);
+ }
} else if (rvh_state_ == STATE_WAITING_FOR_COMMIT) {
- SetState(STATE_SWAPPED_OUT);
+ if (copy_requests_ == 0) {
+ SetState(STATE_SWAPPED_OUT);
+ } else {
+ // Let the copy request complete before swapping out the host so that it
+ // doesn't get destroyed. pending_delete_on_swap_out will be executed from
+ // CopyFromBackingStoreCallback when copy_requests_ goes down to 0.
+ // crbug.com/340682
+ SetPendingShutdown(pending_delete_on_swap_out);
clamy 2014/03/28 11:03:39 There is still a problem with your solution here.
+ }
} else if (rvh_state_ == STATE_DEFAULT) {
// When the RenderView is not live, the RenderFrameHostManager will call
// CommitPending directly, without calling SwapOut on the old RVH. This will
@@ -1719,6 +1745,48 @@ void RenderViewHostImpl::ClearFocusedElement() {
Send(new ViewMsg_ClearFocusedElement(GetRoutingID()));
}
+void RenderViewHostImpl::CopyFromBackingStoreCallback(
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ bool success,
+ const SkBitmap& bitmap) {
+ --copy_requests_;
+ callback.Run(success, bitmap);
+ if (copy_requests_ == 0) {
+ if (!IsRVHStateActive(rvh_state_)) {
+ // RVH was in an active state when |copy_requests_| was incremented, so it
+ // went into inactive state while |copy_requests_| was greater than 0.
+ // This means that WasSwappedOut() was called, but sending of
+ // ViewMsg_WasSwappedOut message was delayed until all copy requests
+ // complete.
+ Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
+ }
+
+ if (rvh_state_ == STATE_PENDING_SHUTDOWN &&
+ pending_shutdown_on_copy_requests_done_) {
+ DCHECK(!pending_shutdown_on_swap_out_.is_null());
+ pending_shutdown_on_swap_out_.Run();
+ }
+ }
+}
+
+void RenderViewHostImpl::CopyFromBackingStore(
+ const gfx::Rect& src_rect,
+ const gfx::Size& accelerated_dst_size,
+ const base::Callback<void(bool, const SkBitmap&)>& callback,
+ const SkBitmap::Config& bitmap_config) {
+ DCHECK(IsRVHStateActive(rvh_state_));
+ if (!IsRVHStateActive(rvh_state_)) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+ ++copy_requests_;
+ RenderWidgetHostImpl::CopyFromBackingStore(src_rect, accelerated_dst_size,
+ base::Bind(&RenderViewHostImpl::CopyFromBackingStoreCallback,
+ weak_factory_.GetWeakPtr(),
+ callback),
+ bitmap_config);
+}
+
void RenderViewHostImpl::Zoom(PageZoom zoom) {
Send(new ViewMsg_Zoom(GetRoutingID(), zoom));
}
« no previous file with comments | « content/browser/renderer_host/render_view_host_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698