Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_widget_host_view_android.cc
index 49ae253..986df1c 100644 (file)
@@ -25,6 +25,7 @@
 #include "cc/output/compositor_frame_ack.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/output/copy_output_result.h"
+#include "cc/output/viewport_selection_bound.h"
 #include "cc/resources/single_release_callback.h"
 #include "cc/trees/layer_tree_host.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
@@ -71,6 +72,7 @@
 #include "ui/events/gesture_detection/motion_event.h"
 #include "ui/gfx/android/device_display_info.h"
 #include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/android/view_configuration.h"
 #include "ui/gfx/display.h"
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size_conversions.h"
@@ -201,6 +203,19 @@ scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
                                     content_view_core->GetDpiScale())));
 }
 
+scoped_ptr<TouchSelectionController> CreateSelectionController(
+    TouchSelectionControllerClient* client,
+    ContentViewCore* content_view_core) {
+  DCHECK(client);
+  DCHECK(content_view_core);
+  int tap_timeout_ms = gfx::ViewConfiguration::GetTapTimeoutInMs();
+  int touch_slop_pixels = gfx::ViewConfiguration::GetTouchSlopInPixels();
+  return make_scoped_ptr(new TouchSelectionController(
+      client,
+      base::TimeDelta::FromMilliseconds(tap_timeout_ms),
+      touch_slop_pixels / content_view_core->GetDpiScale()));
+}
+
 ui::GestureProvider::Config CreateGestureProviderConfig() {
   ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
   config.disable_click_delay =
@@ -224,6 +239,23 @@ bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
 
 }  // anonymous namespace
 
+ReadbackRequest::ReadbackRequest(
+    float scale,
+    SkColorType color_type,
+    gfx::Rect src_subrect,
+    const base::Callback<void(bool, const SkBitmap&)>& result_callback)
+    : scale_(scale),
+      color_type_(color_type),
+      src_subrect_(src_subrect),
+      result_callback_(result_callback) {
+}
+
+ReadbackRequest::ReadbackRequest() {
+}
+
+ReadbackRequest::~ReadbackRequest() {
+}
+
 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
     uint32 output_id,
     scoped_ptr<cc::CompositorFrame> output_frame)
@@ -241,21 +273,19 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
       ime_adapter_android_(this),
       cached_background_color_(SK_ColorWHITE),
       last_output_surface_id_(kUndefinedOutputSurfaceId),
-      weak_ptr_factory_(this),
       overscroll_effect_enabled_(
           !base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kDisableOverscrollEdgeEffect)),
       gesture_provider_(CreateGestureProviderConfig(), this),
       gesture_text_selector_(this),
-      touch_scrolling_(false),
-      potentially_active_fling_count_(0),
       accelerated_surface_route_id_(0),
       using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
                                         widget_host->GetProcess()->GetID(),
                                         widget_host->GetRoutingID()) != NULL),
       frame_evictor_(new DelegatedFrameEvictor(this)),
       locks_on_frame_count_(0),
-      observing_root_window_(false) {
+      observing_root_window_(false),
+      weak_ptr_factory_(this) {
   host_->SetView(this);
   SetContentViewCore(content_view_core);
   ImageTransportFactoryAndroid::AddObserver(this);
@@ -265,6 +295,7 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
   ImageTransportFactoryAndroid::RemoveObserver(this);
   SetContentViewCore(NULL);
   DCHECK(ack_callbacks_.empty());
+  DCHECK(readbacks_waiting_for_frame_.empty());
   if (resource_collection_.get())
     resource_collection_->SetClient(NULL);
 }
@@ -344,19 +375,29 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
   SetSize(rect.size());
 }
 
+void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
+  while (!readbacks_waiting_for_frame_.empty()) {
+    ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
+    readback_request.GetResultCallback().Run(false, SkBitmap());
+    readbacks_waiting_for_frame_.pop();
+  }
+}
+
 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
     float scale,
     SkColorType color_type,
     gfx::Rect src_subrect,
-    const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
+    CopyFromCompositingSurfaceCallback& result_callback) {
   if (!host_ || host_->is_hidden()) {
     result_callback.Run(false, SkBitmap());
     return;
   }
   if (!IsSurfaceAvailableForCopy()) {
-    // TODO(Sikugu): allow a read-back request to wait for a first frame if it
-    // was invoked while no frame was received yet
-    result_callback.Run(false, SkBitmap());
+    // The view is visible, probably the frame has not yet arrived.
+    // Just add the ReadbackRequest to queue and wait for frame arrival
+    // to get this request processed.
+    readbacks_waiting_for_frame_.push(
+        ReadbackRequest(scale, color_type, src_subrect, result_callback));
     return;
   }
 
@@ -375,6 +416,19 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
       src_subrect, dst_size, result_callback, color_type);
 }
 
+scoped_refptr<cc::DelegatedRendererLayer>
+RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
+  DCHECK(frame_provider_);
+
+  scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
+      cc::DelegatedRendererLayer::Create(frame_provider_);
+  delegated_layer->SetBounds(content_size_in_layer_);
+  delegated_layer->SetIsDrawable(true);
+  delegated_layer->SetContentsOpaque(true);
+
+  return delegated_layer;
+}
+
 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
   if (!content_view_core_)
     return false;
@@ -383,13 +437,17 @@ bool RenderWidgetHostViewAndroid::HasValidFrame() const {
 
   if (texture_size_in_layer_.IsEmpty())
     return false;
-
+  // This tell us whether a valid frame has arrived or not.
   if (!frame_evictor_->HasFrame())
     return false;
 
   return true;
 }
 
+gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
+  return last_scroll_offset_;
+}
+
 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
   return content_view_core_->GetViewAndroid();
 }
@@ -417,14 +475,17 @@ void RenderWidgetHostViewAndroid::Focus() {
   host_->SetInputMethodActive(true);
   if (overscroll_effect_)
     overscroll_effect_->Enable();
+  if (selection_controller_)
+    selection_controller_->SetTemporarilyHidden(false);
 }
 
 void RenderWidgetHostViewAndroid::Blur() {
-  host_->ExecuteEditCommand("Unselect", "");
   host_->SetInputMethodActive(false);
   host_->Blur();
   if (overscroll_effect_)
     overscroll_effect_->Disable();
+  if (selection_controller_)
+    selection_controller_->SetTemporarilyHidden(true);
 }
 
 bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -459,6 +520,9 @@ void RenderWidgetHostViewAndroid::Hide() {
     layer_->SetHideLayerAndSubtree(true);
 
   frame_evictor_->SetVisible(false);
+  // We don't know if we will ever get a frame if we are hiding the renderer, so
+  // we need to cancel all requests
+  AbortPendingReadbackRequests();
   WasHidden();
 }
 
@@ -539,11 +603,12 @@ gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
   return content_view_core_->GetPhysicalBackingSize();
 }
 
-float RenderWidgetHostViewAndroid::GetOverdrawBottomHeight() const {
+float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
   if (!content_view_core_)
     return 0.f;
 
-  return content_view_core_->GetOverdrawBottomHeightDip();
+  // The amount that the viewport size given to Blink is shrunk by the URL-bar.
+  return content_view_core_->GetTopControlsLayoutHeightDip();
 }
 
 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
@@ -639,14 +704,21 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
     return true;
   }
 
-  // Short-circuit touch forwarding if no touch handlers exist.
-  if (!host_->ShouldForwardTouchEvent()) {
+  if (host_->ShouldForwardTouchEvent()) {
+    blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event);
+    host_->ForwardTouchEventWithLatencyInfo(web_event,
+                                            CreateLatencyInfo(web_event));
+  } else {
     const bool event_consumed = false;
     gesture_provider_.OnTouchEventAck(event_consumed);
-    return true;
   }
 
-  SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
+  // Send a proactive BeginFrame on the next vsync to reduce latency.
+  // This is good enough as long as the first touch event has Begin semantics
+  // and the actual scroll happens on the next vsync.
+  if (observing_root_window_)
+    RequestVSyncUpdate(BEGIN_FRAME);
+
   return true;
 }
 
@@ -665,10 +737,6 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
   scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
   DCHECK(cancel_event);
   OnTouchEvent(*cancel_event);
-
-  touch_scrolling_ = false;
-  potentially_active_fling_count_ = 0;
-  OnContentScrollingChange();
 }
 
 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
@@ -718,8 +786,14 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
   if (selection_controller_)
     selection_controller_->OnSelectionEmpty(text.empty());
 
-  if (text.empty() || range.is_empty() || !content_view_core_)
+  if (!content_view_core_)
     return;
+  if (range.is_empty()) {
+    content_view_core_->OnSelectionChanged("");
+    return;
+  }
+
+  DCHECK(!text.empty());
   size_t pos = range.GetMin() - offset;
   size_t n = range.length();
 
@@ -736,37 +810,7 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
 
 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
     const ViewHostMsg_SelectionBounds_Params& params) {
-  if (!selection_controller_)
-    return;
-
-  gfx::RectF anchor_rect(params.anchor_rect);
-  gfx::RectF focus_rect(params.focus_rect);
-  if (params.is_anchor_first)
-    std::swap(anchor_rect, focus_rect);
-
-  TouchHandleOrientation anchor_orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED);
-  TouchHandleOrientation focus_orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED);
-  if (params.anchor_rect == params.focus_rect) {
-    if (params.anchor_rect.x() && params.anchor_rect.y())
-      anchor_orientation = focus_orientation = TOUCH_HANDLE_CENTER;
-  } else {
-    anchor_orientation = params.anchor_dir == blink::WebTextDirectionRightToLeft
-                             ? TOUCH_HANDLE_LEFT
-                             : TOUCH_HANDLE_RIGHT;
-    focus_orientation = params.focus_dir == blink::WebTextDirectionRightToLeft
-                            ? TOUCH_HANDLE_RIGHT
-                            : TOUCH_HANDLE_LEFT;
-  }
-
-  selection_controller_->OnSelectionBoundsChanged(anchor_rect,
-                                                  anchor_orientation,
-                                                  true,
-                                                  focus_rect,
-                                                  focus_orientation,
-                                                  true);
-}
-
-void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
+  NOTREACHED() << "Selection bounds should be routed through the compositor.";
 }
 
 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
@@ -777,7 +821,7 @@ void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
-    const base::Callback<void(bool, const SkBitmap&)>& callback,
+    CopyFromCompositingSurfaceCallback& callback,
     const SkColorType color_type) {
   TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
   if ((!host_ || host_->is_hidden()) ||
@@ -815,11 +859,8 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
   DCHECK(compositor);
   DCHECK(frame_provider_);
   scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
-      cc::DelegatedRendererLayer::Create(frame_provider_);
-  delegated_layer->SetBounds(content_size_in_layer_);
+      CreateDelegatedLayerForFrameProvider();
   delegated_layer->SetHideLayerAndSubtree(true);
-  delegated_layer->SetIsDrawable(true);
-  delegated_layer->SetContentsOpaque(true);
   compositor->AttachLayerForReadback(delegated_layer);
 
   readback_layer = delegated_layer;
@@ -848,11 +889,11 @@ bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
 }
 
 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
-    const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) {
+    const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
   if (!content_view_core_)
     return;
 
-  content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
+  content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
 }
 
 scoped_ptr<SyntheticGestureTarget>
@@ -898,6 +939,9 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
   RemoveLayers();
   frame_provider_ = NULL;
   layer_ = NULL;
+  // This gets called when ever any eviction, loosing resources, swapping
+  // problems are encountered and so we abort any pending readbacks here.
+  AbortPendingReadbackRequests();
 }
 
 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
@@ -967,13 +1011,11 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
     const cc::CompositorFrameMetadata& frame_metadata) {
   // Calculate the content size.  This should be 0 if the texture_size is 0.
   gfx::Vector2dF offset;
-  if (texture_size_in_layer_.GetArea() > 0)
-    offset = frame_metadata.location_bar_content_translation;
-  offset.set_y(offset.y() + frame_metadata.overdraw_bottom_height);
-  offset.Scale(frame_metadata.device_scale_factor);
-  content_size_in_layer_ =
-      gfx::Size(texture_size_in_layer_.width() - offset.x(),
-                texture_size_in_layer_.height() - offset.y());
+  if (texture_size_in_layer_.IsEmpty())
+    content_size_in_layer_ = gfx::Size();
+  content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
+      frame_metadata.scrollable_viewport_size,
+      frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
 
   if (overscroll_effect_) {
     overscroll_effect_->UpdateDisplayParameters(
@@ -984,6 +1026,7 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
     uint32 output_surface_id,
     scoped_ptr<cc::CompositorFrame> frame) {
+  last_scroll_offset_ = frame->metadata.root_scroll_offset;
   if (!frame->delegated_frame_data) {
     LOG(ERROR) << "Non-delegated renderer path no longer supported";
     return;
@@ -1016,6 +1059,18 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
   // As the metadata update may trigger view invalidation, always call it after
   // any potential compositor scheduling.
   OnFrameMetadataUpdated(frame->metadata);
+  // Check if we have any pending readbacks, see if we have a frame available
+  // and process them here.
+  if (!readbacks_waiting_for_frame_.empty()) {
+    while (!readbacks_waiting_for_frame_.empty()) {
+      ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
+      GetScaledContentBitmap(readback_request.GetScale(),
+                             readback_request.GetColorFormat(),
+                             readback_request.GetCaptureRect(),
+                             readback_request.GetResultCallback());
+      readbacks_waiting_for_frame_.pop();
+    }
+  }
 }
 
 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
@@ -1153,6 +1208,10 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
   if (!content_view_core_)
     return;
 
+  DCHECK(selection_controller_);
+  selection_controller_->OnSelectionBoundsChanged(
+      frame_metadata.selection_start, frame_metadata.selection_end);
+
   // All offsets and sizes are in CSS pixels.
   content_view_core_->UpdateFrameInfo(
       frame_metadata.root_scroll_offset,
@@ -1162,8 +1221,7 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
       frame_metadata.root_layer_size,
       frame_metadata.scrollable_viewport_size,
       frame_metadata.location_bar_offset,
-      frame_metadata.location_bar_content_translation,
-      frame_metadata.overdraw_bottom_height);
+      frame_metadata.location_bar_content_translation);
 #if defined(VIDEO_HOLE)
   if (host_ && host_->IsRenderView()) {
     RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
@@ -1251,7 +1309,8 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
 
 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
                                                  base::TimeDelta vsync_period) {
-  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
+  TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
+               "frame_time_us", frame_time.ToInternalValue());
   base::TimeTicks display_time = frame_time + vsync_period;
 
   // TODO(brianderson): Use adaptive draw-time estimation.
@@ -1274,15 +1333,6 @@ bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
   return needs_animate;
 }
 
-void RenderWidgetHostViewAndroid::OnContentScrollingChange() {
-  if (selection_controller_)
-    selection_controller_->SetTemporarilyHidden(IsContentScrolling());
-}
-
-bool RenderWidgetHostViewAndroid::IsContentScrolling() const {
-  return touch_scrolling_ || potentially_active_fling_count_ > 0;
-}
-
 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
     int gpu_host_id) {
@@ -1301,6 +1351,9 @@ void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
   if (layer_.get())
     DestroyDelegatedContent();
   frame_evictor_->DiscardedFrame();
+  // We are evicting the delegated frame,
+  // so there should be no pending readback requests
+  DCHECK(readbacks_waiting_for_frame_.empty());
 }
 
 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
@@ -1346,26 +1399,6 @@ void RenderWidgetHostViewAndroid::GestureEventAck(
     DidOverscroll(DidOverscrollParams());
   }
 
-  switch (event.type) {
-    case blink::WebInputEvent::GestureScrollBegin:
-      touch_scrolling_ = true;
-      potentially_active_fling_count_ = 0;
-      OnContentScrollingChange();
-      break;
-    case blink::WebInputEvent::GestureScrollEnd:
-      touch_scrolling_ = false;
-      OnContentScrollingChange();
-      break;
-    case blink::WebInputEvent::GestureFlingStart:
-      touch_scrolling_ = false;
-      if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
-        ++potentially_active_fling_count_;
-      OnContentScrollingChange();
-      break;
-    default:
-      break;
-  }
-
   if (content_view_core_)
     content_view_core_->OnGestureEventAck(event, ack_result);
 }
@@ -1444,19 +1477,6 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
     host_->ForwardKeyboardEvent(event);
 }
 
-void RenderWidgetHostViewAndroid::SendTouchEvent(
-    const blink::WebTouchEvent& event) {
-  if (host_)
-    host_->ForwardTouchEventWithLatencyInfo(event, CreateLatencyInfo(event));
-
-  // Send a proactive BeginFrame on the next vsync to reduce latency.
-  // This is good enough as long as the first touch event has Begin semantics
-  // and the actual scroll happens on the next vsync.
-  // TODO: Is this actually still needed?
-  if (observing_root_window_)
-    RequestVSyncUpdate(BEGIN_FRAME);
-}
-
 void RenderWidgetHostViewAndroid::SendMouseEvent(
     const blink::WebMouseEvent& event) {
   if (host_)
@@ -1498,15 +1518,17 @@ void RenderWidgetHostViewAndroid::OnShowingPastePopup(
   // of the region have been updated, explicitly set the properties now.
   // TODO(jdduke): Remove this workaround when auxiliary paste popup
   // notifications are no longer required, crbug.com/398170.
-  gfx::RectF rect(point, gfx::SizeF());
-  TouchHandleOrientation orientation = TOUCH_HANDLE_CENTER;
-  const bool visible = true;
+  cc::ViewportSelectionBound insertion_bound;
+  insertion_bound.type = cc::SELECTION_BOUND_CENTER;
+  insertion_bound.visible = true;
+  insertion_bound.edge_top = point;
+  insertion_bound.edge_bottom = point;
   HideTextHandles();
   ShowSelectionHandlesAutomatically();
   selection_controller_->OnSelectionEditable(true);
   selection_controller_->OnSelectionEmpty(true);
-  selection_controller_->OnSelectionBoundsChanged(
-      rect, orientation, visible, rect, orientation, visible);
+  selection_controller_->OnSelectionBoundsChanged(insertion_bound,
+                                                  insertion_bound);
 }
 
 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
@@ -1538,11 +1560,6 @@ void RenderWidgetHostViewAndroid::DidOverscroll(
 }
 
 void RenderWidgetHostViewAndroid::DidStopFlinging() {
-  if (potentially_active_fling_count_) {
-    --potentially_active_fling_count_;
-    OnContentScrollingChange();
-  }
-
   if (content_view_core_)
     content_view_core_->DidStopFlinging();
 }
@@ -1583,7 +1600,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
     WasResized();
 
   if (!selection_controller_)
-    selection_controller_.reset(new TouchSelectionController(this));
+    selection_controller_ = CreateSelectionController(this, content_view_core_);
 
   if (overscroll_effect_enabled_ && !overscroll_effect_ &&
       content_view_core_->GetWindowAndroid()->GetCompositor())
@@ -1654,6 +1671,8 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
   if (layer_.get())
     DestroyDelegatedContent();
   DCHECK(ack_callbacks_.empty());
+  // We should not loose a frame if we have readback requests pending.
+  DCHECK(readbacks_waiting_for_frame_.empty());
 }
 
 // static
@@ -1686,10 +1705,10 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
     return;
 
   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
-  if (!bitmap->allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
-                                             dst_size_in_pixel.height(),
-                                             color_type,
-                                             kOpaque_SkAlphaType)))
+  if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+                                                dst_size_in_pixel.height(),
+                                                color_type,
+                                                kOpaque_SkAlphaType)))
     return;
 
   ImageTransportFactoryAndroid* factory =