| Index: content/browser/renderer_host/render_widget_host_impl.cc
|
| diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
|
| index eaff97c650cd7b6a5ac8cc2847d53f9386a07b74..8f6d532221e060b3714d4d72f9446953b291bcc2 100644
|
| --- a/content/browser/renderer_host/render_widget_host_impl.cc
|
| +++ b/content/browser/renderer_host/render_widget_host_impl.cc
|
| @@ -1455,6 +1455,17 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
|
| Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
|
| }
|
|
|
| +void RenderWidgetHostImpl::GetSurfaceSnapshotFromBrowser(
|
| + const GetSnapshotFromBrowserCallback& callback) {
|
| + int id = next_browser_snapshot_id_++;
|
| +
|
| + pending_surface_browser_snapshots_.insert(std::make_pair(id, callback));
|
| + ui::LatencyInfo latency_info;
|
| + latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT, 0,
|
| + id);
|
| + Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
|
| +}
|
| +
|
| const NativeWebKeyboardEvent*
|
| RenderWidgetHostImpl::GetLastKeyboardEvent() const {
|
| return input_router_->GetLastKeyboardEvent();
|
| @@ -2362,26 +2373,64 @@ void RenderWidgetHostImpl::DidReceiveRendererFrame() {
|
| void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
|
| DCHECK(base::MessageLoopForUI::IsCurrent());
|
|
|
| + if (!pending_surface_browser_snapshots_.empty()) {
|
| + GetView()->CopyFromSurface(
|
| + gfx::Rect(), gfx::Size(),
|
| + base::Bind(&RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived,
|
| + weak_factory_.GetWeakPtr(), snapshot_id, 0),
|
| + kN32_SkColorType);
|
| + }
|
| +
|
| + if (!pending_browser_snapshots_.empty()) {
|
| #if defined(OS_ANDROID)
|
| - // On Android, call sites should pass in the bounds with correct offset
|
| - // to capture the intended content area.
|
| - gfx::Rect snapshot_bounds(GetView()->GetViewBounds());
|
| - snapshot_bounds.Offset(0, GetView()->GetNativeView()->content_offset().y());
|
| + // On Android, call sites should pass in the bounds with correct offset
|
| + // to capture the intended content area.
|
| + gfx::Rect snapshot_bounds(GetView()->GetViewBounds());
|
| + snapshot_bounds.Offset(0, GetView()->GetNativeView()->content_offset().y());
|
| #else
|
| - gfx::Rect snapshot_bounds(GetView()->GetViewBounds().size());
|
| + gfx::Rect snapshot_bounds(GetView()->GetViewBounds().size());
|
| #endif
|
|
|
| - gfx::Image image;
|
| - if (ui::GrabViewSnapshot(GetView()->GetNativeView(), snapshot_bounds,
|
| - &image)) {
|
| - OnSnapshotReceived(snapshot_id, image);
|
| - return;
|
| + gfx::Image image;
|
| + if (ui::GrabViewSnapshot(GetView()->GetNativeView(), snapshot_bounds,
|
| + &image)) {
|
| + OnSnapshotReceived(snapshot_id, image);
|
| + return;
|
| + }
|
| +
|
| + ui::GrabViewSnapshotAsync(
|
| + GetView()->GetNativeView(), snapshot_bounds,
|
| + base::Bind(&RenderWidgetHostImpl::OnSnapshotReceived,
|
| + weak_factory_.GetWeakPtr(), snapshot_id));
|
| }
|
| +}
|
|
|
| - ui::GrabViewSnapshotAsync(
|
| - GetView()->GetNativeView(), snapshot_bounds,
|
| - base::Bind(&RenderWidgetHostImpl::OnSnapshotReceived,
|
| - weak_factory_.GetWeakPtr(), snapshot_id));
|
| +void RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived(
|
| + int snapshot_id,
|
| + int retry_count,
|
| + const SkBitmap& bitmap,
|
| + ReadbackResponse response) {
|
| + static const int kMaxRetries = 5;
|
| + if (response != READBACK_SUCCESS && retry_count < kMaxRetries) {
|
| + GetView()->CopyFromSurface(
|
| + gfx::Rect(), gfx::Size(),
|
| + base::Bind(&RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived,
|
| + weak_factory_.GetWeakPtr(), snapshot_id, retry_count + 1),
|
| + kN32_SkColorType);
|
| + return;
|
| + }
|
| + // Any pending snapshots with a lower ID than the one received are considered
|
| + // to be implicitly complete, and returned the same snapshot data.
|
| + const gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap);
|
| + PendingSnapshotMap::iterator it = pending_surface_browser_snapshots_.begin();
|
| + while (it != pending_surface_browser_snapshots_.end()) {
|
| + if (it->first <= snapshot_id) {
|
| + it->second.Run(image);
|
| + pending_surface_browser_snapshots_.erase(it++);
|
| + } else {
|
| + ++it;
|
| + }
|
| + }
|
| }
|
|
|
| void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id,
|
|
|