Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_widget_host_view_android.cc
index c1aa70b..49ae253 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <android/bitmap.h>
 
+#include "base/android/build_info.h"
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
 #include "base/threading/worker_pool.h"
 #include "cc/base/latency_info_swap_promise.h"
 #include "cc/layers/delegated_frame_provider.h"
 #include "cc/layers/delegated_renderer_layer.h"
 #include "cc/layers/layer.h"
-#include "cc/layers/texture_layer.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_ack.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/resources/single_release_callback.h"
 #include "cc/trees/layer_tree_host.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
+#include "content/browser/android/composited_touch_handle_drawable.h"
 #include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/android/edge_effect.h"
+#include "content/browser/android/edge_effect_l.h"
 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
 #include "content/browser/android/overscroll_glow.h"
 #include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/media/media_web_contents_observer.h"
 #include "content/browser/renderer_host/compositor_impl_android.h"
 #include "content/browser/renderer_host/dip_util.h"
 #include "content/browser/renderer_host/image_transport_factory_android.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
+#include "content/browser/renderer_host/input/touch_selection_controller.h"
+#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
+#include "content/browser/renderer_host/input/web_input_event_util.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/gpu/client/gl_helper.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input/did_overscroll_params.h"
 #include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/common/content_switches.h"
@@ -54,6 +66,9 @@
 #include "third_party/khronos/GLES2/gl2ext.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/base/android/window_android.h"
+#include "ui/base/android/window_android_compositor.h"
+#include "ui/events/gesture_detection/gesture_config_helper.h"
+#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/display.h"
@@ -65,25 +80,16 @@ namespace content {
 namespace {
 
 const int kUndefinedOutputSurfaceId = -1;
-static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
 
-void InsertSyncPointAndAckForCompositor(
-    int renderer_host_id,
-    uint32 output_surface_id,
-    int route_id,
-    const gpu::Mailbox& return_mailbox,
-    const gfx::Size return_size) {
-  cc::CompositorFrameAck ack;
-  ack.gl_frame_data.reset(new cc::GLFrameData());
-  if (!return_mailbox.IsZero()) {
-    ack.gl_frame_data->mailbox = return_mailbox;
-    ack.gl_frame_data->size = return_size;
-    ack.gl_frame_data->sync_point =
-        ImageTransportFactoryAndroid::GetInstance()->InsertSyncPoint();
-  }
-  RenderWidgetHostImpl::SendSwapCompositorFrameAck(
-      route_id, output_surface_id, renderer_host_id, ack);
-}
+// Used to accomodate finite precision when comparing scaled viewport and
+// content widths. While this value may seem large, width=device-width on an N7
+// V1 saw errors of ~0.065 between computed window and content widths.
+const float kMobileViewportWidthEpsilon = 0.15f;
+
+// Used for conditional creation of EdgeEffect types for overscroll.
+const int kKitKatMR2SDKVersion = 19;
+
+static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
 
 // Sends an acknowledgement to the renderer of a processed IME event.
 void SendImeEventAck(RenderWidgetHostImpl* host) {
@@ -97,26 +103,23 @@ void CopyFromCompositingSurfaceFinished(
     const base::TimeTicks& start_time,
     scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
     bool result) {
+  TRACE_EVENT0(
+      "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
   bitmap_pixels_lock.reset();
-  release_callback->Run(0, false);
+  uint32 sync_point = 0;
+  if (result) {
+    GLHelper* gl_helper =
+        ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
+    sync_point = gl_helper->InsertSyncPoint();
+  }
+  bool lost_resource = sync_point == 0;
+  release_callback->Run(sync_point, lost_resource);
   UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
                       base::TimeTicks::Now() - start_time);
   callback.Run(result, *bitmap);
 }
 
-bool UsingDelegatedRenderer() {
-  bool using_delegated_renderer = false;
-
-  using_delegated_renderer |= CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableDelegatedRenderer);
-
-  using_delegated_renderer &= !CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableDelegatedRenderer);
-
-  return using_delegated_renderer;
-}
-
-ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent event) {
+ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
   ui::LatencyInfo latency_info;
   // The latency number should only be added if the timestamp is valid.
   if (event.timeStampSeconds) {
@@ -132,35 +135,127 @@ ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent event) {
   return latency_info;
 }
 
+OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
+    const cc::CompositorFrameMetadata& frame_metadata) {
+  const float scale_factor =
+      frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
+
+  // Compute the size and offsets for each edge, where each effect is sized to
+  // the viewport and offset by the distance of each viewport edge to the
+  // respective content edge.
+  OverscrollGlow::DisplayParameters params;
+  params.size = gfx::ScaleSize(
+      frame_metadata.scrollable_viewport_size, scale_factor);
+  params.edge_offsets[OverscrollGlow::EDGE_TOP] =
+      -frame_metadata.root_scroll_offset.y() * scale_factor;
+  params.edge_offsets[OverscrollGlow::EDGE_LEFT] =
+      -frame_metadata.root_scroll_offset.x() * scale_factor;
+  params.edge_offsets[OverscrollGlow::EDGE_BOTTOM] =
+      (frame_metadata.root_layer_size.height() -
+       frame_metadata.root_scroll_offset.y() -
+       frame_metadata.scrollable_viewport_size.height()) *
+      scale_factor;
+  params.edge_offsets[OverscrollGlow::EDGE_RIGHT] =
+      (frame_metadata.root_layer_size.width() -
+       frame_metadata.root_scroll_offset.x() -
+       frame_metadata.scrollable_viewport_size.width()) *
+      scale_factor;
+
+  return params;
+}
+
+bool UseEdgeEffectL() {
+  static bool use_edge_effect_l =
+      base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
+  return use_edge_effect_l;
+}
+
+scoped_ptr<EdgeEffectBase> CreateEdgeEffect(
+    ui::SystemUIResourceManager* resource_manager,
+    float device_scale_factor) {
+  DCHECK(resource_manager);
+  if (UseEdgeEffectL())
+    return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
+
+  return scoped_ptr<EdgeEffectBase>(
+      new EdgeEffect(resource_manager, device_scale_factor));
+}
+
+scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
+    ContentViewCore* content_view_core) {
+  DCHECK(content_view_core);
+  ui::WindowAndroidCompositor* compositor =
+      content_view_core->GetWindowAndroid()->GetCompositor();
+  DCHECK(compositor);
+  ui::SystemUIResourceManager* system_resource_manager =
+      &compositor->GetSystemUIResourceManager();
+
+  if (UseEdgeEffectL())
+    EdgeEffectL::PreloadResources(system_resource_manager);
+  else
+    EdgeEffect::PreloadResources(system_resource_manager);
+
+  return make_scoped_ptr(
+      new OverscrollGlow(base::Bind(&CreateEdgeEffect,
+                                    system_resource_manager,
+                                    content_view_core->GetDpiScale())));
+}
+
+ui::GestureProvider::Config CreateGestureProviderConfig() {
+  ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
+  config.disable_click_delay =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableClickDelay);
+  return config;
+}
+
+bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
+  return frame_metadata.min_page_scale_factor ==
+         frame_metadata.max_page_scale_factor;
+}
+
+bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
+  float window_width_dip =
+      frame_metadata.page_scale_factor *
+          frame_metadata.scrollable_viewport_size.width();
+  float content_width_css = frame_metadata.root_layer_size.width();
+  return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
+}
+
 }  // anonymous namespace
 
+RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
+    uint32 output_id,
+    scoped_ptr<cc::CompositorFrame> output_frame)
+    : output_surface_id(output_id), frame(output_frame.Pass()) {}
+
+RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
+
 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
     RenderWidgetHostImpl* widget_host,
     ContentViewCoreImpl* content_view_core)
     : host_(widget_host),
-      needs_begin_frame_(false),
-      are_layers_attached_(!widget_host->is_hidden()),
+      outstanding_vsync_requests_(0),
+      is_showing_(!widget_host->is_hidden()),
       content_view_core_(NULL),
       ime_adapter_android_(this),
       cached_background_color_(SK_ColorWHITE),
-      texture_id_in_layer_(0),
       last_output_surface_id_(kUndefinedOutputSurfaceId),
       weak_ptr_factory_(this),
       overscroll_effect_enabled_(
-          !CommandLine::ForCurrentProcess()->
-              HasSwitch(switches::kDisableOverscrollEdgeEffect)),
-      overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)),
-      flush_input_requested_(false),
+          !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)) {
-  if (!UsingDelegatedRenderer()) {
-    texture_layer_ = cc::TextureLayer::Create(NULL);
-    layer_ = texture_layer_;
-  }
-
+      frame_evictor_(new DelegatedFrameEvictor(this)),
+      locks_on_frame_count_(0),
+      observing_root_window_(false) {
   host_->SetView(this);
   SetContentViewCore(content_view_core);
   ImageTransportFactoryAndroid::AddObserver(this);
@@ -170,14 +265,6 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
   ImageTransportFactoryAndroid::RemoveObserver(this);
   SetContentViewCore(NULL);
   DCHECK(ack_callbacks_.empty());
-  if (texture_id_in_layer_) {
-    ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
-        texture_id_in_layer_);
-  }
-
-  if (texture_layer_.get())
-    texture_layer_->ClearClient();
-
   if (resource_collection_.get())
     resource_collection_->SetClient(NULL);
 }
@@ -192,8 +279,6 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
                         OnDidChangeBodyBackgroundColor)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
                         OnSetNeedsBeginFrame)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
-                        OnTextInputStateChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
                         OnSmartClipDataExtracted)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -224,10 +309,12 @@ void RenderWidgetHostViewAndroid::WasShown() {
   if (!host_ || !host_->is_hidden())
     return;
 
-  host_->WasShown();
+  host_->WasShown(ui::LatencyInfo());
 
-  if (content_view_core_ && !using_synchronous_compositor_)
-    content_view_core_->GetWindowAndroid()->AddObserver(this);
+  if (content_view_core_) {
+    StartObservingRootWindow();
+    RequestVSyncUpdate(BEGIN_FRAME);
+  }
 }
 
 void RenderWidgetHostViewAndroid::WasHidden() {
@@ -240,8 +327,7 @@ void RenderWidgetHostViewAndroid::WasHidden() {
   // utilization.
   host_->WasHidden();
 
-  if (content_view_core_ && !using_synchronous_compositor_)
-    content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+  StopObservingRootWindow();
 }
 
 void RenderWidgetHostViewAndroid::WasResized() {
@@ -252,87 +338,54 @@ void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
   // Ignore the given size as only the Java code has the power to
   // resize the view on Android.
   default_size_ = size;
-  WasResized();
 }
 
 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
   SetSize(rect.size());
 }
 
-blink::WebGLId RenderWidgetHostViewAndroid::GetScaledContentTexture(
+void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
     float scale,
-    gfx::Size* out_size) {
-  gfx::Size size(gfx::ToCeiledSize(
-      gfx::ScaleSize(texture_size_in_layer_, scale)));
-
-  if (!CompositorImpl::IsInitialized() ||
-      texture_id_in_layer_ == 0 ||
-      texture_size_in_layer_.IsEmpty() ||
-      size.IsEmpty()) {
-    if (out_size)
-        out_size->SetSize(0, 0);
-
-    return 0;
+    SkColorType color_type,
+    gfx::Rect src_subrect,
+    const base::Callback<void(bool, const SkBitmap&)>& 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());
+    return;
   }
 
-  if (out_size)
-    *out_size = size;
-
-  GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
-  return helper->CopyAndScaleTexture(texture_id_in_layer_,
-                                     texture_size_in_layer_,
-                                     size,
-                                     true,
-                                     GLHelper::SCALER_QUALITY_FAST);
-}
-
-bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) {
-  if (!CompositorImpl::IsInitialized() ||
-      texture_id_in_layer_ == 0 ||
-      texture_size_in_layer_.IsEmpty())
-    return false;
-
-  gfx::JavaBitmap bitmap(jbitmap);
-
-  // TODO(dtrainor): Eventually add support for multiple formats here.
-  DCHECK(bitmap.format() == ANDROID_BITMAP_FORMAT_RGBA_8888);
-
-  GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
-
-  GLuint texture = helper->CopyAndScaleTexture(
-      texture_id_in_layer_,
-      texture_size_in_layer_,
-      bitmap.size(),
-      true,
-      GLHelper::SCALER_QUALITY_FAST);
-  if (texture == 0u)
-    return false;
-
-  helper->ReadbackTextureSync(texture,
-                              gfx::Rect(bitmap.size()),
-                              static_cast<unsigned char*> (bitmap.pixels()),
-                              SkBitmap::kARGB_8888_Config);
-
-  gpu::gles2::GLES2Interface* gl =
-      ImageTransportFactoryAndroid::GetInstance()->GetContextGL();
-  gl->DeleteTextures(1, &texture);
-
-  return true;
+  gfx::Size bounds = layer_->bounds();
+  if (src_subrect.IsEmpty())
+    src_subrect = gfx::Rect(bounds);
+  DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
+  DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
+  const gfx::Display& display =
+      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+  float device_scale_factor = display.device_scale_factor();
+  DCHECK_GT(device_scale_factor, 0);
+  gfx::Size dst_size(
+      gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
+  CopyFromCompositingSurface(
+      src_subrect, dst_size, result_callback, color_type);
 }
 
 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
   if (!content_view_core_)
     return false;
+  if (!layer_)
+    return false;
+
   if (texture_size_in_layer_.IsEmpty())
     return false;
 
-  if (UsingDelegatedRenderer()) {
-    if (!delegated_renderer_layer_.get())
-      return false;
-  } else {
-    if (texture_id_in_layer_ == 0)
-      return false;
-  }
+  if (!frame_evictor_->HasFrame())
+    return false;
 
   return true;
 }
@@ -353,7 +406,6 @@ RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
 }
 
 void RenderWidgetHostViewAndroid::MovePluginWindows(
-    const gfx::Vector2d& scroll_offset,
     const std::vector<WebPluginGeometry>& moves) {
   // We don't have plugin windows on Android. Do nothing. Note: this is called
   // from RenderWidgetHost::OnUpdateRect which is itself invoked while
@@ -363,8 +415,7 @@ void RenderWidgetHostViewAndroid::MovePluginWindows(
 void RenderWidgetHostViewAndroid::Focus() {
   host_->Focus();
   host_->SetInputMethodActive(true);
-  ResetClipping();
-  if (overscroll_effect_enabled_)
+  if (overscroll_effect_)
     overscroll_effect_->Enable();
 }
 
@@ -372,7 +423,8 @@ void RenderWidgetHostViewAndroid::Blur() {
   host_->ExecuteEditCommand("Unselect", "");
   host_->SetInputMethodActive(false);
   host_->Blur();
-  overscroll_effect_->Disable();
+  if (overscroll_effect_)
+    overscroll_effect_->Disable();
 }
 
 bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -387,22 +439,24 @@ bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
 }
 
 void RenderWidgetHostViewAndroid::Show() {
-  if (are_layers_attached_)
+  if (is_showing_)
     return;
 
-  are_layers_attached_ = true;
-  AttachLayers();
+  is_showing_ = true;
+  if (layer_)
+    layer_->SetHideLayerAndSubtree(false);
 
   frame_evictor_->SetVisible(true);
   WasShown();
 }
 
 void RenderWidgetHostViewAndroid::Hide() {
-  if (!are_layers_attached_)
+  if (!is_showing_)
     return;
 
-  are_layers_attached_ = false;
-  RemoveLayers();
+  is_showing_ = false;
+  if (layer_ && locks_on_frame_count_ == 0)
+    layer_->SetHideLayerAndSubtree(true);
 
   frame_evictor_->SetVisible(false);
   WasHidden();
@@ -412,30 +466,70 @@ bool RenderWidgetHostViewAndroid::IsShowing() {
   // ContentViewCoreImpl represents the native side of the Java
   // ContentViewCore.  It being NULL means that it is not attached
   // to the View system yet, so we treat this RWHVA as hidden.
-  return are_layers_attached_ && content_view_core_;
+  return is_showing_ && content_view_core_;
 }
 
-void RenderWidgetHostViewAndroid::LockResources() {
+void RenderWidgetHostViewAndroid::LockCompositingSurface() {
   DCHECK(HasValidFrame());
   DCHECK(host_);
-  DCHECK(!host_->is_hidden());
+  DCHECK(frame_evictor_->HasFrame());
   frame_evictor_->LockFrame();
+  locks_on_frame_count_++;
 }
 
-void RenderWidgetHostViewAndroid::UnlockResources() {
+void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
+  if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
+    return;
+
   DCHECK(HasValidFrame());
   frame_evictor_->UnlockFrame();
+  locks_on_frame_count_--;
+
+  if (locks_on_frame_count_ == 0) {
+    if (last_frame_info_) {
+      InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
+                                  last_frame_info_->frame.Pass());
+      last_frame_info_.reset();
+    }
+
+    if (!is_showing_ && layer_)
+      layer_->SetHideLayerAndSubtree(true);
+  }
+}
+
+void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
+    const TextSurroundingSelectionCallback& callback) {
+  // Only one outstanding request is allowed at any given time.
+  DCHECK(!callback.is_null());
+  text_surrounding_selection_callback_ = callback;
+}
+
+void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
+    const base::string16& content,
+    size_t start_offset,
+    size_t end_offset) {
+  if (text_surrounding_selection_callback_.is_null())
+    return;
+  text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
+  text_surrounding_selection_callback_.Reset();
+}
+
+void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
+  if (!frame_evictor_->HasFrame()) {
+    DCHECK_EQ(locks_on_frame_count_, 0u);
+    return;
+  }
+  while (locks_on_frame_count_ > 0) {
+    UnlockCompositingSurface();
+  }
+  RunAckCallbacks();
 }
 
 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
   if (!content_view_core_)
     return gfx::Rect(default_size_);
 
-  gfx::Size size = content_view_core_->GetViewportSizeDip();
-  gfx::Size offset = content_view_core_->GetViewportSizeOffsetDip();
-  size.Enlarge(-offset.width(), -offset.height());
-
-  return gfx::Rect(size);
+  return gfx::Rect(content_view_core_->GetViewSize());
 }
 
 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
@@ -461,24 +555,26 @@ void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
   // is TabContentsDelegate.
 }
 
-void RenderWidgetHostViewAndroid::TextInputTypeChanged(
-    ui::TextInputType type,
-    ui::TextInputMode input_mode,
-    bool can_compose_inline) {
-  // Unused on Android, which uses OnTextInputChanged instead.
-}
-
-int RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
-  return reinterpret_cast<int>(&ime_adapter_android_);
+long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
+  return reinterpret_cast<intptr_t>(&ime_adapter_android_);
 }
 
-void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
+void RenderWidgetHostViewAndroid::TextInputStateChanged(
     const ViewHostMsg_TextInputState_Params& params) {
-  // If an acknowledgement is required for this event, regardless of how we exit
-  // from this method, we must acknowledge that we processed the input state
-  // change.
+  if (selection_controller_) {
+    // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
+    // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
+    // while this call is present to ensure consistency with IME after
+    // navigation and tab focus changes
+    const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
+    selection_controller_->OnSelectionEditable(is_editable_node);
+  }
+
+  // If the change is not originated from IME (e.g. Javascript, autofill),
+  // send back the renderer an acknowledgement, regardless of how we exit from
+  // this method.
   base::ScopedClosureRunner ack_caller;
-  if (params.require_ack)
+  if (params.is_non_ime_change)
     ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
 
   if (!IsShowing())
@@ -486,10 +582,10 @@ void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
 
   content_view_core_->UpdateImeAdapter(
       GetNativeImeAdapter(),
-      static_cast<int>(params.type),
+      static_cast<int>(params.type), params.flags,
       params.value, params.selection_start, params.selection_end,
       params.composition_start, params.composition_end,
-      params.show_ime_if_needed, params.require_ack);
+      params.show_ime_if_needed, params.is_non_ime_change);
 }
 
 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
@@ -502,36 +598,14 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
     content_view_core_->OnBackgroundColorChanged(color);
 }
 
-void RenderWidgetHostViewAndroid::SendBeginFrame(
-    const cc::BeginFrameArgs& args) {
-  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
-  if (!host_)
-    return;
-
-  if (flush_input_requested_) {
-    flush_input_requested_ = false;
-    host_->FlushInput();
-    content_view_core_->RemoveBeginFrameSubscriber();
-  }
-
-  host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
-}
-
-void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(
-    bool enabled) {
+void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
+  DCHECK(!using_synchronous_compositor_);
   TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
                "enabled", enabled);
-  // ContentViewCoreImpl handles multiple subscribers to the BeginFrame, so
-  // we have to make sure calls to ContentViewCoreImpl's
-  // {Add,Remove}BeginFrameSubscriber are balanced, even if
-  // RenderWidgetHostViewAndroid's may not be.
-  if (content_view_core_ && needs_begin_frame_ != enabled) {
-    if (enabled)
-      content_view_core_->AddBeginFrameSubscriber();
-    else
-      content_view_core_->RemoveBeginFrameSubscriber();
-    needs_begin_frame_ = enabled;
-  }
+  if (enabled)
+    RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
+  else
+    outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
 }
 
 void RenderWidgetHostViewAndroid::OnStartContentIntent(
@@ -541,13 +615,69 @@ void RenderWidgetHostViewAndroid::OnStartContentIntent(
 }
 
 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
-    const base::string16& result) {
-  // Custom serialization over IPC isn't allowed normally for security reasons.
-  // Since this feature is only used in (single-process) WebView, there are no
-  // security issues. Enforce that it's only called in single process mode.
-  CHECK(RenderProcessHost::run_renderer_in_process());
+    const base::string16& text,
+    const base::string16& html,
+    const gfx::Rect rect) {
   if (content_view_core_)
-    content_view_core_->OnSmartClipDataExtracted(result);
+    content_view_core_->OnSmartClipDataExtracted(text, html, rect);
+}
+
+bool RenderWidgetHostViewAndroid::OnTouchEvent(
+    const ui::MotionEvent& event) {
+  if (!host_)
+    return false;
+
+  if (selection_controller_ &&
+      selection_controller_->WillHandleTouchEvent(event))
+    return true;
+
+  if (!gesture_provider_.OnTouchEvent(event))
+    return false;
+
+  if (gesture_text_selector_.OnTouchEvent(event)) {
+    gesture_provider_.OnTouchEventAck(false);
+    return true;
+  }
+
+  // Short-circuit touch forwarding if no touch handlers exist.
+  if (!host_->ShouldForwardTouchEvent()) {
+    const bool event_consumed = false;
+    gesture_provider_.OnTouchEventAck(event_consumed);
+    return true;
+  }
+
+  SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
+  return true;
+}
+
+bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
+    const ui::MotionEvent& event) {
+  return selection_controller_ &&
+         selection_controller_->WillHandleTouchEvent(event);
+}
+
+void RenderWidgetHostViewAndroid::ResetGestureDetection() {
+  const ui::MotionEvent* current_down_event =
+      gesture_provider_.GetCurrentDownEvent();
+  if (!current_down_event)
+    return;
+
+  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) {
+  gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
+}
+
+void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
+    bool enabled) {
+  gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
 }
 
 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
@@ -556,14 +686,8 @@ void RenderWidgetHostViewAndroid::ImeCancelComposition() {
 
 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
   ime_adapter_android_.FocusedNodeChanged(is_editable_node);
-}
-
-void RenderWidgetHostViewAndroid::DidUpdateBackingStore(
-    const gfx::Rect& scroll_rect,
-    const gfx::Vector2d& scroll_delta,
-    const std::vector<gfx::Rect>& copy_rects,
-    const std::vector<ui::LatencyInfo>& latency_info) {
-  NOTIMPLEMENTED();
+  if (selection_controller_)
+    selection_controller_->OnSelectionEditable(is_editable_node);
 }
 
 void RenderWidgetHostViewAndroid::RenderProcessGone(
@@ -591,6 +715,9 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
                                                    const gfx::Range& range) {
   RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
 
+  if (selection_controller_)
+    selection_controller_->OnSelectionEmpty(text.empty());
+
   if (text.empty() || range.is_empty() || !content_view_core_)
     return;
   size_t pos = range.GetMin() - offset;
@@ -609,35 +736,52 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
 
 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
     const ViewHostMsg_SelectionBounds_Params& params) {
-  if (content_view_core_) {
-    content_view_core_->OnSelectionBoundsChanged(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;
   }
-}
 
-void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
+  selection_controller_->OnSelectionBoundsChanged(anchor_rect,
+                                                  anchor_orientation,
+                                                  true,
+                                                  focus_rect,
+                                                  focus_orientation,
+                                                  true);
 }
 
-BackingStore* RenderWidgetHostViewAndroid::AllocBackingStore(
-    const gfx::Size& size) {
-  NOTIMPLEMENTED();
-  return NULL;
+void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
 }
 
-void RenderWidgetHostViewAndroid::SetBackground(const SkBitmap& background) {
-  RenderWidgetHostViewBase::SetBackground(background);
-  host_->Send(new ViewMsg_SetBackground(host_->GetRoutingID(), background));
+void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
+  RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
+  host_->SetBackgroundOpaque(opaque);
 }
 
 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const base::Callback<void(bool, const SkBitmap&)>& callback,
-    const SkBitmap::Config bitmap_config) {
-  // Only ARGB888 and RGB565 supported as of now.
-  bool format_support = ((bitmap_config == SkBitmap::kRGB_565_Config) ||
-                         (bitmap_config == SkBitmap::kARGB_8888_Config));
-  if (!format_support) {
-    DCHECK(format_support);
+    const SkColorType color_type) {
+  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
+  if ((!host_ || host_->is_hidden()) ||
+      !IsReadbackConfigSupported(color_type)) {
     callback.Run(false, SkBitmap());
     return;
   }
@@ -646,52 +790,49 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
     callback.Run(false, SkBitmap());
     return;
   }
-  ImageTransportFactoryAndroid* factory =
-      ImageTransportFactoryAndroid::GetInstance();
-  GLHelper* gl_helper = factory->GetGLHelper();
-  if (!gl_helper)
-    return;
-  bool check_rgb565_support = gl_helper->CanUseRgb565Readback();
-  if ((bitmap_config == SkBitmap::kRGB_565_Config) &&
-      !check_rgb565_support) {
-    LOG(ERROR) << "Readbackformat rgb565  not supported";
-    callback.Run(false, SkBitmap());
-    return;
-  }
   const gfx::Display& display =
       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
   float device_scale_factor = display.device_scale_factor();
-
-  DCHECK_EQ(device_scale_factor,
-            ui::GetImageScale(GetScaleFactorForView(this)));
-
-  const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
+  gfx::Size dst_size_in_pixel =
+      ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
   gfx::Rect src_subrect_in_pixel =
       ConvertRectToPixel(device_scale_factor, src_subrect);
 
   if (using_synchronous_compositor_) {
-    SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback);
+    SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
+                            color_type);
     UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
                         base::TimeTicks::Now() - start_time);
     return;
   }
+
   scoped_ptr<cc::CopyOutputRequest> request;
-  if (src_subrect_in_pixel.size() == dst_size_in_pixel) {
-      request = cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
-          &RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult,
-          dst_size_in_pixel,
-          start_time,
-          callback));
-  } else {
-      request = cc::CopyOutputRequest::CreateRequest(base::Bind(
-          &RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult,
-          dst_size_in_pixel,
-          bitmap_config,
-          start_time,
-          callback));
-  }
+  scoped_refptr<cc::Layer> readback_layer;
+  DCHECK(content_view_core_);
+  DCHECK(content_view_core_->GetWindowAndroid());
+  ui::WindowAndroidCompositor* compositor =
+      content_view_core_->GetWindowAndroid()->GetCompositor();
+  DCHECK(compositor);
+  DCHECK(frame_provider_);
+  scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
+      cc::DelegatedRendererLayer::Create(frame_provider_);
+  delegated_layer->SetBounds(content_size_in_layer_);
+  delegated_layer->SetHideLayerAndSubtree(true);
+  delegated_layer->SetIsDrawable(true);
+  delegated_layer->SetContentsOpaque(true);
+  compositor->AttachLayerForReadback(delegated_layer);
+
+  readback_layer = delegated_layer;
+  request = cc::CopyOutputRequest::CreateRequest(
+      base::Bind(&RenderWidgetHostViewAndroid::
+                     PrepareTextureCopyOutputResultForDelegatedReadback,
+                 dst_size_in_pixel,
+                 color_type,
+                 start_time,
+                 readback_layer,
+                 callback));
   request->set_area(src_subrect_in_pixel);
-  layer_->RequestCopyOfOutput(request.Pass());
+  readback_layer->RequestCopyOfOutput(request.Pass());
 }
 
 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
@@ -720,11 +861,9 @@ RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
       host_, content_view_core_->CreateTouchEventSynthesizer()));
 }
 
-void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
-}
-
 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
     uint32 output_surface_id) {
+  DCHECK(host_);
   cc::CompositorFrameAck ack;
   if (resource_collection_.get())
     resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
@@ -734,15 +873,30 @@ void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
                                                    ack);
 }
 
+void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
+    uint32 output_surface_id) {
+  DCHECK(resource_collection_);
+
+  cc::CompositorFrameAck ack;
+  resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+  DCHECK(!ack.resources.empty());
+
+  RenderWidgetHostImpl::SendReclaimCompositorResources(
+      host_->GetRoutingID(),
+      output_surface_id,
+      host_->GetProcess()->GetID(),
+      ack);
+}
+
 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
-  // TODO(danakj): If no ack is pending, collect and send resources now.
+  if (ack_callbacks_.size())
+    return;
+  SendReturnedDelegatedResources(last_output_surface_id_);
 }
 
 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
-  if (are_layers_attached_)
-    RemoveLayers();
+  RemoveLayers();
   frame_provider_ = NULL;
-  delegated_renderer_layer_ = NULL;
   layer_ = NULL;
 }
 
@@ -752,14 +906,12 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
   bool has_content = !texture_size_in_layer_.IsEmpty();
 
   if (output_surface_id != last_output_surface_id_) {
-    // TODO(danakj): Lose all resources and send them back here, such as:
-    // resource_collection_->LoseAllResources();
-    // SendReturnedDelegatedResources(last_output_surface_id_);
-
     // Drop the cc::DelegatedFrameResourceCollection so that we will not return
     // any resources from the old output surface with the new output surface id.
     if (resource_collection_.get()) {
       resource_collection_->SetClient(NULL);
+      if (resource_collection_->LoseAllResources())
+        SendReturnedDelegatedResources(last_output_surface_id_);
       resource_collection_ = NULL;
     }
     DestroyDelegatedContent();
@@ -767,6 +919,14 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
     last_output_surface_id_ = output_surface_id;
   }
 
+  // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
+  // renderer frame, assuming that the browser compositor will scale
+  // it back up to device scale.  But on Android we put our browser layers in
+  // physical pixels and set our browser CC device_scale_factor to 1, so this
+  // suppresses the transform.  This line may need to be removed when fixing
+  // http://crbug.com/384134 or http://crbug.com/310763
+  frame_data->device_scale_factor = 1.0f;
+
   if (!has_content) {
     DestroyDelegatedContent();
   } else {
@@ -776,26 +936,21 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
     }
     if (!frame_provider_ ||
         texture_size_in_layer_ != frame_provider_->frame_size()) {
-      if (are_layers_attached_)
-        RemoveLayers();
+      RemoveLayers();
       frame_provider_ = new cc::DelegatedFrameProvider(
           resource_collection_.get(), frame_data.Pass());
-      delegated_renderer_layer_ =
-          cc::DelegatedRendererLayer::Create(frame_provider_);
-      layer_ = delegated_renderer_layer_;
-      if (are_layers_attached_)
-        AttachLayers();
+      layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
+      AttachLayers();
     } else {
       frame_provider_->SetFrameData(frame_data.Pass());
     }
   }
 
-  if (delegated_renderer_layer_.get()) {
-    delegated_renderer_layer_->SetDisplaySize(texture_size_in_layer_);
-    delegated_renderer_layer_->SetIsDrawable(true);
-    delegated_renderer_layer_->SetContentsOpaque(true);
-    delegated_renderer_layer_->SetBounds(content_size_in_layer_);
-    delegated_renderer_layer_->SetNeedsDisplay();
+  if (layer_.get()) {
+    layer_->SetIsDrawable(true);
+    layer_->SetContentsOpaque(true);
+    layer_->SetBounds(content_size_in_layer_);
+    layer_->SetNeedsDisplay();
   }
 
   base::Closure ack_callback =
@@ -803,10 +958,9 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
                  weak_ptr_factory_.GetWeakPtr(),
                  output_surface_id);
 
+  ack_callbacks_.push(ack_callback);
   if (host_->is_hidden())
-    ack_callback.Run();
-  else
-    ack_callbacks_.push(ack_callback);
+    RunAckCallbacks();
 }
 
 void RenderWidgetHostViewAndroid::ComputeContentsSize(
@@ -820,55 +974,28 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
   content_size_in_layer_ =
       gfx::Size(texture_size_in_layer_.width() - offset.x(),
                 texture_size_in_layer_.height() - offset.y());
-  // Content size changes should be reflected in associated animation effects.
-  UpdateAnimationSize(frame_metadata);
+
+  if (overscroll_effect_) {
+    overscroll_effect_->UpdateDisplayParameters(
+        CreateOverscrollDisplayParameters(frame_metadata));
+  }
 }
 
-void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
+void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
     uint32 output_surface_id,
     scoped_ptr<cc::CompositorFrame> frame) {
-  // Always let ContentViewCore know about the new frame first, so it can decide
-  // to schedule a Draw immediately when it sees the texture layer invalidation.
-  UpdateContentViewCoreFrameMetadata(frame->metadata);
-
-  if (frame->delegated_frame_data) {
-    DCHECK(UsingDelegatedRenderer());
-
-    DCHECK(frame->delegated_frame_data);
-    DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
-
-    cc::RenderPass* root_pass =
-        frame->delegated_frame_data->render_pass_list.back();
-    texture_size_in_layer_ = root_pass->output_rect.size();
-    ComputeContentsSize(frame->metadata);
-
-    SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
+  if (!frame->delegated_frame_data) {
+    LOG(ERROR) << "Non-delegated renderer path no longer supported";
     return;
   }
 
-  DCHECK(!UsingDelegatedRenderer());
-
-  if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
+  if (locks_on_frame_count_ > 0) {
+    DCHECK(HasValidFrame());
+    RetainFrame(output_surface_id, frame.Pass());
     return;
-
-  if (output_surface_id != last_output_surface_id_) {
-    current_mailbox_ = gpu::Mailbox();
-    last_output_surface_id_ = kUndefinedOutputSurfaceId;
   }
 
-  base::Closure callback = base::Bind(&InsertSyncPointAndAckForCompositor,
-                                      host_->GetProcess()->GetID(),
-                                      output_surface_id,
-                                      host_->GetRoutingID(),
-                                      current_mailbox_,
-                                      texture_size_in_layer_);
-  ImageTransportFactoryAndroid::GetInstance()->WaitSyncPoint(
-      frame->gl_frame_data->sync_point);
-
-  texture_size_in_layer_ = frame->gl_frame_data->size;
-  ComputeContentsSize(frame->metadata);
-
-  if (layer_->layer_tree_host()) {
+  if (layer_ && layer_->layer_tree_host()) {
     for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
       scoped_ptr<cc::SwapPromise> swap_promise(
           new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
@@ -876,22 +1003,60 @@ void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
     }
   }
 
-  BuffersSwapped(frame->gl_frame_data->mailbox, output_surface_id, callback);
+  DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
+
+  cc::RenderPass* root_pass =
+      frame->delegated_frame_data->render_pass_list.back();
+  texture_size_in_layer_ = root_pass->output_rect.size();
+  ComputeContentsSize(frame->metadata);
+
+  SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
   frame_evictor_->SwappedFrame(!host_->is_hidden());
+
+  // As the metadata update may trigger view invalidation, always call it after
+  // any potential compositor scheduling.
+  OnFrameMetadataUpdated(frame->metadata);
+}
+
+void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
+    uint32 output_surface_id,
+    scoped_ptr<cc::CompositorFrame> frame) {
+  InternalSwapCompositorFrame(output_surface_id, frame.Pass());
+}
+
+void RenderWidgetHostViewAndroid::RetainFrame(
+    uint32 output_surface_id,
+    scoped_ptr<cc::CompositorFrame> frame) {
+  DCHECK(locks_on_frame_count_);
+
+  // Store the incoming frame so that it can be swapped when all the locks have
+  // been released. If there is already a stored frame, then replace and skip
+  // the previous one but make sure we still eventually send the ACK. Holding
+  // the ACK also blocks the renderer when its max_frames_pending is reached.
+  if (last_frame_info_) {
+    base::Closure ack_callback =
+        base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   last_frame_info_->output_surface_id);
+
+    ack_callbacks_.push(ack_callback);
+  }
+
+  last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
 }
 
 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
     const cc::CompositorFrameMetadata& frame_metadata) {
   // This is a subset of OnSwapCompositorFrame() used in the synchronous
   // compositor flow.
-  UpdateContentViewCoreFrameMetadata(frame_metadata);
+  OnFrameMetadataUpdated(frame_metadata);
   ComputeContentsSize(frame_metadata);
 
   // DevTools ScreenCast support for Android WebView.
-  if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) {
+  WebContents* web_contents = content_view_core_->GetWebContents();
+  if (DevToolsAgentHost::HasFor(web_contents)) {
     scoped_refptr<DevToolsAgentHost> dtah =
-        DevToolsAgentHost::GetOrCreateFor(
-            RenderViewHost::From(GetRenderWidgetHost()));
+        DevToolsAgentHost::GetOrCreateFor(web_contents);
     // Unblock the compositor.
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
@@ -902,13 +1067,56 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
 }
 
 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
-  layer_->SetContentsOpaque(!enabled);
+  if (layer_)
+    layer_->SetContentsOpaque(!enabled);
+}
+
+bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
+  // The synchronous (WebView) compositor does not have a proper browser
+  // compositor with which to drive animations.
+  return !using_synchronous_compositor_;
+}
+
+void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
+  DCHECK(content_view_core_);
+  DCHECK(!using_synchronous_compositor_);
+  content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
+}
+
+void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
+  MoveCaret(gfx::Point(position.x(), position.y()));
+}
+
+void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
+    const gfx::PointF& start,
+    const gfx::PointF& end) {
+  DCHECK(content_view_core_);
+  content_view_core_->SelectBetweenCoordinates(start, end);
+}
+
+void RenderWidgetHostViewAndroid::OnSelectionEvent(
+    SelectionEventType event,
+    const gfx::PointF& position) {
+  DCHECK(content_view_core_);
+  content_view_core_->OnSelectionEvent(event, position);
+}
+
+scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
+  DCHECK(content_view_core_);
+  if (using_synchronous_compositor_)
+    return content_view_core_->CreatePopupTouchHandleDrawable();
+
+  return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
+      content_view_core_->GetLayer(),
+      content_view_core_->GetDpiScale(),
+      base::android::GetApplicationContext()));
 }
 
 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
     const gfx::Rect& src_subrect_in_pixel,
     const gfx::Size& dst_size_in_pixel,
-    const base::Callback<void(bool, const SkBitmap&)>& callback) {
+    const base::Callback<void(bool, const SkBitmap&)>& callback,
+    const SkColorType color_type) {
   SynchronousCompositor* compositor =
       SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
                                         host_->GetRoutingID());
@@ -918,10 +1126,10 @@ void RenderWidgetHostViewAndroid::SynchronousCopyContents(
   }
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                   dst_size_in_pixel.width(),
-                   dst_size_in_pixel.height());
-  bitmap.allocPixels();
+  bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+                                       dst_size_in_pixel.height(),
+                                       color_type,
+                                       kPremul_SkAlphaType));
   SkCanvas canvas(bitmap);
   canvas.scale(
       (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
@@ -930,21 +1138,39 @@ void RenderWidgetHostViewAndroid::SynchronousCopyContents(
   callback.Run(true, bitmap);
 }
 
-void RenderWidgetHostViewAndroid::UpdateContentViewCoreFrameMetadata(
+void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
     const cc::CompositorFrameMetadata& frame_metadata) {
-  if (content_view_core_) {
-    // All offsets and sizes are in CSS pixels.
-    content_view_core_->UpdateFrameInfo(
-        frame_metadata.root_scroll_offset,
-        frame_metadata.page_scale_factor,
-        gfx::Vector2dF(frame_metadata.min_page_scale_factor,
-                       frame_metadata.max_page_scale_factor),
-        frame_metadata.root_layer_size,
-        frame_metadata.viewport_size,
-        frame_metadata.location_bar_offset,
-        frame_metadata.location_bar_content_translation,
-        frame_metadata.overdraw_bottom_height);
+
+  // Disable double tap zoom for pages that have a width=device-width or
+  // narrower viewport (indicating that this is a mobile-optimized or responsive
+  // web design, so text will be legible without zooming). Also disable
+  // double tap and pinch for pages that prevent zooming in or out.
+  bool has_mobile_viewport = HasMobileViewport(frame_metadata);
+  bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
+  gesture_provider_.SetDoubleTapSupportForPageEnabled(
+      !has_fixed_page_scale && !has_mobile_viewport);
+
+  if (!content_view_core_)
+    return;
+
+  // All offsets and sizes are in CSS pixels.
+  content_view_core_->UpdateFrameInfo(
+      frame_metadata.root_scroll_offset,
+      frame_metadata.page_scale_factor,
+      gfx::Vector2dF(frame_metadata.min_page_scale_factor,
+                     frame_metadata.max_page_scale_factor),
+      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);
+#if defined(VIDEO_HOLE)
+  if (host_ && host_->IsRenderView()) {
+    RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
+        RenderViewHost::From(host_));
+    rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
   }
+#endif  // defined(VIDEO_HOLE)
 }
 
 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
@@ -958,34 +1184,6 @@ void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
   NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
 }
 
-void RenderWidgetHostViewAndroid::BuffersSwapped(
-    const gpu::Mailbox& mailbox,
-    uint32_t output_surface_id,
-    const base::Closure& ack_callback) {
-  ImageTransportFactoryAndroid* factory =
-      ImageTransportFactoryAndroid::GetInstance();
-
-  if (!texture_id_in_layer_) {
-    texture_id_in_layer_ = factory->CreateTexture();
-    texture_layer_->SetTextureId(texture_id_in_layer_);
-    texture_layer_->SetIsDrawable(true);
-    texture_layer_->SetContentsOpaque(true);
-  }
-
-  ImageTransportFactoryAndroid::GetInstance()->AcquireTexture(
-      texture_id_in_layer_, mailbox.name);
-
-  ResetClipping();
-
-  current_mailbox_ = mailbox;
-  last_output_surface_id_ = output_surface_id;
-
-  if (host_->is_hidden())
-    ack_callback.Run();
-  else
-    ack_callbacks_.push(ack_callback);
-}
-
 void RenderWidgetHostViewAndroid::AttachLayers() {
   if (!content_view_core_)
     return;
@@ -993,34 +1191,96 @@ void RenderWidgetHostViewAndroid::AttachLayers() {
     return;
 
   content_view_core_->AttachLayer(layer_);
-  if (overscroll_effect_enabled_)
+  if (overscroll_effect_)
     overscroll_effect_->Enable();
+  layer_->SetHideLayerAndSubtree(!is_showing_);
 }
 
 void RenderWidgetHostViewAndroid::RemoveLayers() {
   if (!content_view_core_)
     return;
+
   if (!layer_.get())
     return;
 
   content_view_core_->RemoveLayer(layer_);
-  overscroll_effect_->Disable();
+  if (overscroll_effect_)
+    overscroll_effect_->Disable();
+}
+
+void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
+  // The synchronous compositor does not requre BeginFrame messages.
+  if (using_synchronous_compositor_)
+    requests &= FLUSH_INPUT;
+
+  bool should_request_vsync = !outstanding_vsync_requests_ && requests;
+  outstanding_vsync_requests_ |= requests;
+  // Note that if we're not currently observing the root window, outstanding
+  // vsync requests will be pushed if/when we resume observing in
+  // |StartObservingRootWindow()|.
+  if (observing_root_window_ && should_request_vsync)
+    content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
+}
+
+void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
+  DCHECK(content_view_core_);
+  if (observing_root_window_)
+    return;
+
+  observing_root_window_ = true;
+  content_view_core_->GetWindowAndroid()->AddObserver(this);
+
+  // Clear existing vsync requests to allow a request to the new window.
+  uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
+  outstanding_vsync_requests_ = 0;
+  RequestVSyncUpdate(outstanding_vsync_requests);
+}
+
+void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
+  if (!content_view_core_) {
+    DCHECK(!observing_root_window_);
+    return;
+  }
+
+  if (!observing_root_window_)
+    return;
+
+  observing_root_window_ = false;
+  content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+}
+
+void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
+                                                 base::TimeDelta vsync_period) {
+  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
+  base::TimeTicks display_time = frame_time + vsync_period;
+
+  // TODO(brianderson): Use adaptive draw-time estimation.
+  base::TimeDelta estimated_browser_composite_time =
+      base::TimeDelta::FromMicroseconds(
+          (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
+
+  base::TimeTicks deadline = display_time - estimated_browser_composite_time;
+
+  host_->Send(new ViewMsg_BeginFrame(
+      host_->GetRoutingID(),
+      cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
 }
 
 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
-  return overscroll_effect_->Animate(frame_time);
+  bool needs_animate =
+      overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
+  if (selection_controller_)
+    needs_animate |= selection_controller_->Animate(frame_time);
+  return needs_animate;
 }
 
-void RenderWidgetHostViewAndroid::UpdateAnimationSize(
-    const cc::CompositorFrameMetadata& frame_metadata) {
-  // Disable edge effects for axes on which scrolling is impossible.
-  gfx::SizeF ceiled_viewport_size =
-      gfx::ToCeiledSize(frame_metadata.viewport_size);
-  overscroll_effect_->set_horizontal_overscroll_enabled(
-      ceiled_viewport_size.width() < frame_metadata.root_layer_size.width());
-  overscroll_effect_->set_vertical_overscroll_enabled(
-      ceiled_viewport_size.height() < frame_metadata.root_layer_size.height());
-  overscroll_effect_->set_size(content_size_in_layer_);
+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(
@@ -1038,16 +1298,7 @@ void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
 }
 
 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
-  if (texture_id_in_layer_) {
-    texture_layer_->SetTextureId(0);
-    texture_layer_->SetIsDrawable(false);
-    ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
-        texture_id_in_layer_);
-    texture_id_in_layer_ = 0;
-    current_mailbox_ = gpu::Mailbox();
-    last_output_surface_id_ = kUndefinedOutputSurfaceId;
-  }
-  if (delegated_renderer_layer_.get())
+  if (layer_.get())
     DestroyDelegatedContent();
   frame_evictor_->DiscardedFrame();
 }
@@ -1081,48 +1332,63 @@ gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
 
 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
-  if (content_view_core_)
-    content_view_core_->ConfirmTouchEvent(ack_result);
-}
-
-void RenderWidgetHostViewAndroid::SetHasHorizontalScrollbar(
-    bool has_horizontal_scrollbar) {
-  // intentionally empty, like RenderWidgetHostViewViews
-}
-
-void RenderWidgetHostViewAndroid::SetScrollOffsetPinning(
-    bool is_pinned_to_left, bool is_pinned_to_right) {
-  // intentionally empty, like RenderWidgetHostViewViews
-}
-
-void RenderWidgetHostViewAndroid::UnhandledWheelEvent(
-    const blink::WebMouseWheelEvent& event) {
-  // intentionally empty, like RenderWidgetHostViewViews
+  const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+  gesture_provider_.OnTouchEventAck(event_consumed);
 }
 
 void RenderWidgetHostViewAndroid::GestureEventAck(
-    int gesture_event_type,
+    const blink::WebGestureEvent& event,
     InputEventAckState ack_result) {
-  // Scroll events.
-  if (gesture_event_type == blink::WebInputEvent::GestureScrollBegin) {
-    content_view_core_->OnScrollBeginEventAck();
-  }
-  if (gesture_event_type == blink::WebInputEvent::GestureScrollUpdate &&
-      ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
-    content_view_core_->OnScrollUpdateGestureConsumed();
-  }
-  if (gesture_event_type == blink::WebInputEvent::GestureScrollEnd) {
-    content_view_core_->OnScrollEndEventAck();
+  // The overscroll effect requires an explicit release signal that may not be
+  // sent from the renderer compositor.
+  if (event.type == blink::WebInputEvent::GestureScrollEnd ||
+      event.type == blink::WebInputEvent::GestureFlingStart) {
+    DidOverscroll(DidOverscrollParams());
   }
 
-  // Fling events.
-  if (gesture_event_type == blink::WebInputEvent::GestureFlingStart) {
-    content_view_core_->OnFlingStartEventAck(ack_result);
+  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);
 }
 
 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
     const blink::WebInputEvent& input_event) {
+  if (selection_controller_) {
+    switch (input_event.type) {
+      case blink::WebInputEvent::GestureLongPress:
+        selection_controller_->OnLongPressEvent();
+        break;
+      case blink::WebInputEvent::GestureTap:
+        selection_controller_->OnTapEvent();
+        break;
+      default:
+        break;
+    }
+  }
+
+  if (content_view_core_ &&
+      content_view_core_->FilterInputEvent(input_event))
+    return INPUT_EVENT_ACK_STATE_CONSUMED;
+
   if (!host_)
     return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 
@@ -1145,77 +1411,20 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
 }
 
 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
-  if (flush_input_requested_ || !content_view_core_)
-    return;
-  flush_input_requested_ = true;
-  content_view_core_->AddBeginFrameSubscriber();
-}
-
-void RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManagerIfNeeded() {
-  if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete)
-    return;
-
-  if (!GetBrowserAccessibilityManager()) {
-    base::android::ScopedJavaLocalRef<jobject> obj;
-    if (content_view_core_)
-      obj = content_view_core_->GetJavaObject();
-    SetBrowserAccessibilityManager(
-        new BrowserAccessibilityManagerAndroid(
-            obj, BrowserAccessibilityManagerAndroid::GetEmptyDocument(), this));
-  }
-}
-
-void RenderWidgetHostViewAndroid::SetAccessibilityFocus(int acc_obj_id) {
-  if (!host_)
-    return;
-
-  host_->AccessibilitySetFocus(acc_obj_id);
-}
-
-void RenderWidgetHostViewAndroid::AccessibilityDoDefaultAction(int acc_obj_id) {
-  if (!host_)
-    return;
-
-  host_->AccessibilityDoDefaultAction(acc_obj_id);
-}
-
-void RenderWidgetHostViewAndroid::AccessibilityScrollToMakeVisible(
-    int acc_obj_id, gfx::Rect subfocus) {
-  if (!host_)
-    return;
-
-  host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
-}
-
-void RenderWidgetHostViewAndroid::AccessibilityScrollToPoint(
-    int acc_obj_id, gfx::Point point) {
-  if (!host_)
-    return;
-
-  host_->AccessibilityScrollToPoint(acc_obj_id, point);
+  TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
+  RequestVSyncUpdate(FLUSH_INPUT);
 }
 
-void RenderWidgetHostViewAndroid::AccessibilitySetTextSelection(
-    int acc_obj_id, int start_offset, int end_offset) {
-  if (!host_)
-    return;
-
-  host_->AccessibilitySetTextSelection(
-      acc_obj_id, start_offset, end_offset);
-}
-
-gfx::Point RenderWidgetHostViewAndroid::GetLastTouchEventLocation() const {
-  NOTIMPLEMENTED();
-  // Only used on Win8
-  return gfx::Point();
-}
-
-void RenderWidgetHostViewAndroid::FatalAccessibilityTreeError() {
-  if (!host_)
-    return;
-
-  host_->FatalAccessibilityTreeError();
-  SetBrowserAccessibilityManager(NULL);
+BrowserAccessibilityManager*
+    RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
+        BrowserAccessibilityDelegate* delegate) {
+  base::android::ScopedJavaLocalRef<jobject> obj;
+  if (content_view_core_)
+    obj = content_view_core_->GetJavaObject();
+  return new BrowserAccessibilityManagerAndroid(
+      obj,
+      BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
+      delegate);
 }
 
 bool RenderWidgetHostViewAndroid::LockMouse() {
@@ -1239,8 +1448,14 @@ 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) {
@@ -1257,121 +1472,122 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
 void RenderWidgetHostViewAndroid::SendGestureEvent(
     const blink::WebGestureEvent& event) {
   // Sending a gesture that may trigger overscroll should resume the effect.
-  if (overscroll_effect_enabled_)
-   overscroll_effect_->Enable();
+  if (overscroll_effect_)
+    overscroll_effect_->Enable();
 
   if (host_)
     host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
 }
 
-void RenderWidgetHostViewAndroid::SelectRange(const gfx::Point& start,
-                                              const gfx::Point& end) {
-  if (host_)
-    host_->SelectRange(start, end);
-}
-
 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
   if (host_)
     host_->MoveCaret(point);
 }
 
-void RenderWidgetHostViewAndroid::RequestContentClipping(
-    const gfx::Rect& clipping,
-    const gfx::Size& content_size) {
-  // A focused view provides its own clipping.
-  if (HasFocus())
-    return;
-
-  ClipContents(clipping, content_size);
+void RenderWidgetHostViewAndroid::HideTextHandles() {
+  if (selection_controller_)
+    selection_controller_->HideAndDisallowShowingAutomatically();
 }
 
-void RenderWidgetHostViewAndroid::ResetClipping() {
-  ClipContents(gfx::Rect(gfx::Point(), content_size_in_layer_),
-               content_size_in_layer_);
-}
-
-void RenderWidgetHostViewAndroid::ClipContents(const gfx::Rect& clipping,
-                                               const gfx::Size& content_size) {
-  if (!texture_id_in_layer_ || content_size_in_layer_.IsEmpty())
-    return;
-
-  gfx::Size clipped_content(content_size_in_layer_);
-  clipped_content.SetToMin(clipping.size());
-  texture_layer_->SetBounds(clipped_content);
-  texture_layer_->SetNeedsDisplay();
-
-  if (texture_size_in_layer_.IsEmpty()) {
-    texture_layer_->SetUV(gfx::PointF(), gfx::PointF());
+void RenderWidgetHostViewAndroid::OnShowingPastePopup(
+    const gfx::PointF& point) {
+  if (!selection_controller_)
     return;
-  }
 
-  gfx::PointF offset(
-      clipping.x() + content_size_in_layer_.width() - content_size.width(),
-      clipping.y() + content_size_in_layer_.height() - content_size.height());
-  offset.SetToMax(gfx::PointF());
-
-  gfx::Vector2dF uv_scale(1.f / texture_size_in_layer_.width(),
-                          1.f / texture_size_in_layer_.height());
-  texture_layer_->SetUV(
-      gfx::PointF(offset.x() * uv_scale.x(),
-                  offset.y() * uv_scale.y()),
-      gfx::PointF((offset.x() + clipped_content.width()) * uv_scale.x(),
-                  (offset.y() + clipped_content.height()) * uv_scale.y()));
+  // As the paste popup may be triggered *before* the bounds and editability
+  // 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;
+  HideTextHandles();
+  ShowSelectionHandlesAutomatically();
+  selection_controller_->OnSelectionEditable(true);
+  selection_controller_->OnSelectionEmpty(true);
+  selection_controller_->OnSelectionBoundsChanged(
+      rect, orientation, visible, rect, orientation, visible);
 }
 
 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
   return cached_background_color_;
 }
 
-void RenderWidgetHostViewAndroid::OnOverscrolled(
-    gfx::Vector2dF accumulated_overscroll,
-    gfx::Vector2dF current_fling_velocity) {
-  if (!content_view_core_ || !are_layers_attached_)
+void RenderWidgetHostViewAndroid::DidOverscroll(
+    const DidOverscrollParams& params) {
+  if (!content_view_core_ || !layer_ || !is_showing_)
     return;
 
-  if (overscroll_effect_->OnOverscrolled(content_view_core_->GetLayer(),
-                                         base::TimeTicks::Now(),
-                                         accumulated_overscroll,
-                                         current_fling_velocity)) {
-    content_view_core_->SetNeedsAnimate();
+  const float device_scale_factor = content_view_core_->GetDpiScale();
+
+  if (overscroll_effect_ &&
+      overscroll_effect_->OnOverscrolled(
+          content_view_core_->GetLayer(),
+          base::TimeTicks::Now(),
+          gfx::ScaleVector2d(params.accumulated_overscroll,
+                             device_scale_factor),
+          gfx::ScaleVector2d(params.latest_overscroll_delta,
+                             device_scale_factor),
+          gfx::ScaleVector2d(params.current_fling_velocity,
+                             device_scale_factor),
+          gfx::ScaleVector2d(
+              params.causal_event_viewport_point.OffsetFromOrigin(),
+              device_scale_factor))) {
+    SetNeedsAnimate();
   }
 }
 
 void RenderWidgetHostViewAndroid::DidStopFlinging() {
+  if (potentially_active_fling_count_) {
+    --potentially_active_fling_count_;
+    OnContentScrollingChange();
+  }
+
   if (content_view_core_)
     content_view_core_->DidStopFlinging();
 }
 
 void RenderWidgetHostViewAndroid::SetContentViewCore(
     ContentViewCoreImpl* content_view_core) {
-  RunAckCallbacks();
-
-  if (are_layers_attached_)
-    RemoveLayers();
-
-  if (content_view_core_ && !using_synchronous_compositor_)
-    content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+  RemoveLayers();
+  StopObservingRootWindow();
+
+  bool resize = false;
+  if (content_view_core != content_view_core_) {
+    overscroll_effect_.reset();
+    selection_controller_.reset();
+    ReleaseLocksOnSurface();
+    resize = true;
+  }
 
   content_view_core_ = content_view_core;
 
-  if (GetBrowserAccessibilityManager()) {
+  BrowserAccessibilityManager* manager = NULL;
+  if (host_)
+    manager = host_->GetRootBrowserAccessibilityManager();
+  if (manager) {
     base::android::ScopedJavaLocalRef<jobject> obj;
     if (content_view_core_)
       obj = content_view_core_->GetJavaObject();
-    GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()->
-        SetContentViewCore(obj);
+    manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
   }
 
-  if (are_layers_attached_) {
-    AttachLayers();
-    if (content_view_core_ && !using_synchronous_compositor_)
-      content_view_core_->GetWindowAndroid()->AddObserver(this);
-  }
+  AttachLayers();
 
-  // Ensure ContentsViewCore is aware of the current touch handling state, eg.
-  // in case we've already been running JS for the page as part of preload.
-  if (content_view_core_ && host_)
-    content_view_core_->HasTouchEventHandlers(host_->has_touch_handler());
+  if (!content_view_core_)
+    return;
+
+  StartObservingRootWindow();
+
+  if (resize)
+    WasResized();
+
+  if (!selection_controller_)
+    selection_controller_.reset(new TouchSelectionController(this));
+
+  if (overscroll_effect_enabled_ && !overscroll_effect_ &&
+      content_view_core_->GetWindowAndroid()->GetCompositor())
+    overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
 }
 
 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
@@ -1381,56 +1597,105 @@ void RenderWidgetHostViewAndroid::RunAckCallbacks() {
   }
 }
 
-void RenderWidgetHostViewAndroid::HasTouchEventHandlers(
-    bool need_touch_events) {
-  if (content_view_core_)
-    content_view_core_->HasTouchEventHandlers(need_touch_events);
+void RenderWidgetHostViewAndroid::OnGestureEvent(
+    const ui::GestureEventData& gesture) {
+  if (gesture_text_selector_.OnGestureEvent(gesture))
+    return;
+
+  SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
 }
 
 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
   RunAckCallbacks();
 }
 
+
+void RenderWidgetHostViewAndroid::OnAttachCompositor() {
+  DCHECK(content_view_core_);
+  if (overscroll_effect_enabled_ && !overscroll_effect_)
+    overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
+}
+
 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
   DCHECK(content_view_core_);
   DCHECK(!using_synchronous_compositor_);
   RunAckCallbacks();
+  overscroll_effect_.reset();
+}
+
+void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
+                                          base::TimeDelta vsync_period) {
+  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
+  if (!host_)
+    return;
+
+  const uint32 current_vsync_requests = outstanding_vsync_requests_;
+  outstanding_vsync_requests_ = 0;
+
+  if (current_vsync_requests & FLUSH_INPUT)
+    host_->FlushInput();
+
+  if (current_vsync_requests & BEGIN_FRAME ||
+      current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
+    SendBeginFrame(frame_time, vsync_period);
+  }
+
+  if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
+    RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
+}
+
+void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
+  if (Animate(begin_frame_time))
+    SetNeedsAnimate();
 }
 
 void RenderWidgetHostViewAndroid::OnLostResources() {
-  if (texture_layer_.get())
-    texture_layer_->SetIsDrawable(false);
-  if (delegated_renderer_layer_.get())
+  ReleaseLocksOnSurface();
+  if (layer_.get())
     DestroyDelegatedContent();
-  texture_id_in_layer_ = 0;
-  RunAckCallbacks();
+  DCHECK(ack_callbacks_.empty());
+}
+
+// static
+void
+RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
+    const gfx::Size& dst_size_in_pixel,
+    const SkColorType color_type,
+    const base::TimeTicks& start_time,
+    scoped_refptr<cc::Layer> readback_layer,
+    const base::Callback<void(bool, const SkBitmap&)>& callback,
+    scoped_ptr<cc::CopyOutputResult> result) {
+  readback_layer->RemoveFromParent();
+  PrepareTextureCopyOutputResult(
+      dst_size_in_pixel, color_type, start_time, callback, result.Pass());
 }
 
 // static
 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
     const gfx::Size& dst_size_in_pixel,
-    const SkBitmap::Config bitmap_config,
+    const SkColorType color_type,
     const base::TimeTicks& start_time,
     const base::Callback<void(bool, const SkBitmap&)>& callback,
     scoped_ptr<cc::CopyOutputResult> result) {
-  DCHECK(result->HasTexture());
   base::ScopedClosureRunner scoped_callback_runner(
       base::Bind(callback, false, SkBitmap()));
+  TRACE_EVENT0("cc",
+               "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
 
   if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
     return;
 
   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
-  bitmap->setConfig(bitmap_config,
-                    dst_size_in_pixel.width(),
-                    dst_size_in_pixel.height(),
-                    0, kOpaque_SkAlphaType);
-  if (!bitmap->allocPixels())
+  if (!bitmap->allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+                                             dst_size_in_pixel.height(),
+                                             color_type,
+                                             kOpaque_SkAlphaType)))
     return;
 
   ImageTransportFactoryAndroid* factory =
       ImageTransportFactoryAndroid::GetInstance();
   GLHelper* gl_helper = factory->GetGLHelper();
+
   if (!gl_helper)
     return;
 
@@ -1448,51 +1713,71 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
   ignore_result(scoped_callback_runner.Release());
 
   gl_helper->CropScaleReadbackAndCleanMailbox(
-      texture_mailbox.name(),
+      texture_mailbox.mailbox(),
       texture_mailbox.sync_point(),
       result->size(),
       gfx::Rect(result->size()),
       dst_size_in_pixel,
       pixels,
-      bitmap_config,
+      color_type,
       base::Bind(&CopyFromCompositingSurfaceFinished,
                  callback,
                  base::Passed(&release_callback),
                  base::Passed(&bitmap),
                  start_time,
-                 base::Passed(&bitmap_pixels_lock)));
+                 base::Passed(&bitmap_pixels_lock)),
+      GLHelper::SCALER_QUALITY_GOOD);
 }
 
-// static
-void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult(
-    const gfx::Size& dst_size_in_pixel,
-    const base::TimeTicks& start_time,
-    const base::Callback<void(bool, const SkBitmap&)>& callback,
-    scoped_ptr<cc::CopyOutputResult> result) {
-  DCHECK(result->HasBitmap());
-  base::ScopedClosureRunner scoped_callback_runner(
-      base::Bind(callback, false, SkBitmap()));
+bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
+    SkColorType color_type) {
+  ImageTransportFactoryAndroid* factory =
+      ImageTransportFactoryAndroid::GetInstance();
+  GLHelper* gl_helper = factory->GetGLHelper();
+  if (!gl_helper)
+    return false;
+  return gl_helper->IsReadbackConfigSupported(color_type);
+}
 
-  if (!result->HasBitmap() || result->IsEmpty() || result->size().IsEmpty())
-    return;
+SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
+  // Define the criteria here. If say the 16 texture readback is
+  // supported we should go with that (this degrades quality)
+  // or stick back to the default format.
+  if (base::SysInfo::IsLowEndDevice()) {
+    if (IsReadbackConfigSupported(kRGB_565_SkColorType))
+      return kRGB_565_SkColorType;
+  }
+  return kN32_SkColorType;
+}
 
-  scoped_ptr<SkBitmap> source = result->TakeBitmap();
-  DCHECK(source);
-  if (!source)
-    return;
+void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
+  // Fake a long press to allow automatic selection handle showing.
+  if (selection_controller_)
+    selection_controller_->OnLongPressEvent();
+}
 
-  DCHECK_EQ(source->width(), dst_size_in_pixel.width());
-  DCHECK_EQ(source->height(), dst_size_in_pixel.height());
+void RenderWidgetHostViewAndroid::SelectRange(
+    float x1, float y1, float x2, float y2) {
+  if (content_view_core_)
+    static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
+        SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
+}
 
-  ignore_result(scoped_callback_runner.Release());
-  UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
-                      base::TimeTicks::Now() - start_time);
+void RenderWidgetHostViewAndroid::Unselect() {
+  if (content_view_core_)
+    content_view_core_->GetWebContents()->Unselect();
+}
 
-  callback.Run(true, *source);
+void RenderWidgetHostViewAndroid::LongPress(
+    base::TimeTicks time, float x, float y) {
+  blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
+      blink::WebInputEvent::GestureLongPress,
+      (time - base::TimeTicks()).InSecondsF(), x, y);
+  SendGestureEvent(long_press);
 }
 
 // static
-void RenderWidgetHostViewPort::GetDefaultScreenInfo(
+void RenderWidgetHostViewBase::GetDefaultScreenInfo(
     blink::WebScreenInfo* results) {
   const gfx::Display& display =
       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
@@ -1500,20 +1785,13 @@ void RenderWidgetHostViewPort::GetDefaultScreenInfo(
   // TODO(husky): Remove any system controls from availableRect.
   results->availableRect = display.work_area();
   results->deviceScaleFactor = display.device_scale_factor();
+  results->orientationAngle = display.RotationAsDegree();
+  results->orientationType =
+      RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
   gfx::DeviceDisplayInfo info;
   results->depth = info.GetBitsPerPixel();
   results->depthPerComponent = info.GetBitsPerComponent();
   results->isMonochrome = (results->depthPerComponent == 0);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostView, public:
-
-// static
-RenderWidgetHostView*
-RenderWidgetHostView::CreateViewForWidget(RenderWidgetHost* widget) {
-  RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
-  return new RenderWidgetHostViewAndroid(rwhi, NULL);
-}
-
 } // namespace content