1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/render_widget_host_view_android.h"
6
7#include <android/bitmap.h>
8
9#include "base/android/build_info.h"
10#include "base/basictypes.h"
11#include "base/bind.h"
12#include "base/callback_helpers.h"
13#include "base/command_line.h"
14#include "base/logging.h"
15#include "base/message_loop/message_loop.h"
16#include "base/metrics/histogram.h"
17#include "base/strings/utf_string_conversions.h"
18#include "base/sys_info.h"
19#include "base/threading/worker_pool.h"
20#include "cc/base/latency_info_swap_promise.h"
21#include "cc/layers/delegated_frame_provider.h"
22#include "cc/layers/delegated_renderer_layer.h"
23#include "cc/layers/layer.h"
24#include "cc/output/compositor_frame.h"
25#include "cc/output/compositor_frame_ack.h"
26#include "cc/output/copy_output_request.h"
27#include "cc/output/copy_output_result.h"
28#include "cc/output/viewport_selection_bound.h"
29#include "cc/resources/single_release_callback.h"
30#include "cc/trees/layer_tree_host.h"
31#include "content/browser/accessibility/browser_accessibility_manager_android.h"
32#include "content/browser/android/composited_touch_handle_drawable.h"
33#include "content/browser/android/content_view_core_impl.h"
34#include "content/browser/android/edge_effect.h"
35#include "content/browser/android/edge_effect_l.h"
36#include "content/browser/android/in_process/synchronous_compositor_impl.h"
37#include "content/browser/android/overscroll_glow.h"
38#include "content/browser/devtools/render_view_devtools_agent_host.h"
39#include "content/browser/gpu/compositor_util.h"
40#include "content/browser/gpu/gpu_data_manager_impl.h"
41#include "content/browser/gpu/gpu_process_host_ui_shim.h"
42#include "content/browser/gpu/gpu_surface_tracker.h"
43#include "content/browser/media/media_web_contents_observer.h"
44#include "content/browser/renderer_host/compositor_impl_android.h"
45#include "content/browser/renderer_host/dip_util.h"
46#include "content/browser/renderer_host/image_transport_factory_android.h"
47#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
48#include "content/browser/renderer_host/input/touch_selection_controller.h"
49#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
50#include "content/browser/renderer_host/input/web_input_event_util.h"
51#include "content/browser/renderer_host/render_process_host_impl.h"
52#include "content/browser/renderer_host/render_view_host_impl.h"
53#include "content/browser/renderer_host/render_widget_host_impl.h"
54#include "content/common/gpu/client/gl_helper.h"
55#include "content/common/gpu/gpu_messages.h"
56#include "content/common/input/did_overscroll_params.h"
57#include "content/common/input_messages.h"
58#include "content/common/view_messages.h"
59#include "content/public/browser/browser_thread.h"
60#include "content/public/browser/devtools_agent_host.h"
61#include "content/public/browser/render_view_host.h"
62#include "content/public/common/content_switches.h"
63#include "gpu/command_buffer/client/gles2_interface.h"
64#include "gpu/config/gpu_driver_bug_workaround_type.h"
65#include "skia/ext/image_operations.h"
66#include "third_party/khronos/GLES2/gl2.h"
67#include "third_party/khronos/GLES2/gl2ext.h"
68#include "third_party/skia/include/core/SkCanvas.h"
69#include "ui/base/android/window_android.h"
70#include "ui/base/android/window_android_compositor.h"
71#include "ui/events/gesture_detection/gesture_config_helper.h"
72#include "ui/events/gesture_detection/motion_event.h"
73#include "ui/gfx/android/device_display_info.h"
74#include "ui/gfx/android/java_bitmap.h"
75#include "ui/gfx/android/view_configuration.h"
76#include "ui/gfx/display.h"
77#include "ui/gfx/screen.h"
78#include "ui/gfx/size_conversions.h"
79
80namespace content {
81
82namespace {
83
84const int kUndefinedOutputSurfaceId = -1;
85
86// Used to accomodate finite precision when comparing scaled viewport and
87// content widths. While this value may seem large, width=device-width on an N7
88// V1 saw errors of ~0.065 between computed window and content widths.
89const float kMobileViewportWidthEpsilon = 0.15f;
90
91// Used for conditional creation of EdgeEffect types for overscroll.
92const int kKitKatMR2SDKVersion = 19;
93
94static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
95
96// Sends an acknowledgement to the renderer of a processed IME event.
97void SendImeEventAck(RenderWidgetHostImpl* host) {
98  host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
99}
100
101void CopyFromCompositingSurfaceFinished(
102    const base::Callback<void(bool, const SkBitmap&)>& callback,
103    scoped_ptr<cc::SingleReleaseCallback> release_callback,
104    scoped_ptr<SkBitmap> bitmap,
105    const base::TimeTicks& start_time,
106    scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
107    bool result) {
108  TRACE_EVENT0(
109      "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
110  bitmap_pixels_lock.reset();
111  uint32 sync_point = 0;
112  if (result) {
113    GLHelper* gl_helper =
114        ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
115    sync_point = gl_helper->InsertSyncPoint();
116  }
117  bool lost_resource = sync_point == 0;
118  release_callback->Run(sync_point, lost_resource);
119  UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
120                      base::TimeTicks::Now() - start_time);
121  callback.Run(result, *bitmap);
122}
123
124ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
125  ui::LatencyInfo latency_info;
126  // The latency number should only be added if the timestamp is valid.
127  if (event.timeStampSeconds) {
128    const int64 time_micros = static_cast<int64>(
129        event.timeStampSeconds * base::Time::kMicrosecondsPerSecond);
130    latency_info.AddLatencyNumberWithTimestamp(
131        ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
132        0,
133        0,
134        base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
135        1);
136  }
137  return latency_info;
138}
139
140OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
141    const cc::CompositorFrameMetadata& frame_metadata) {
142  const float scale_factor =
143      frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
144
145  // Compute the size and offsets for each edge, where each effect is sized to
146  // the viewport and offset by the distance of each viewport edge to the
147  // respective content edge.
148  OverscrollGlow::DisplayParameters params;
149  params.size = gfx::ScaleSize(
150      frame_metadata.scrollable_viewport_size, scale_factor);
151  params.edge_offsets[OverscrollGlow::EDGE_TOP] =
152      -frame_metadata.root_scroll_offset.y() * scale_factor;
153  params.edge_offsets[OverscrollGlow::EDGE_LEFT] =
154      -frame_metadata.root_scroll_offset.x() * scale_factor;
155  params.edge_offsets[OverscrollGlow::EDGE_BOTTOM] =
156      (frame_metadata.root_layer_size.height() -
157       frame_metadata.root_scroll_offset.y() -
158       frame_metadata.scrollable_viewport_size.height()) *
159      scale_factor;
160  params.edge_offsets[OverscrollGlow::EDGE_RIGHT] =
161      (frame_metadata.root_layer_size.width() -
162       frame_metadata.root_scroll_offset.x() -
163       frame_metadata.scrollable_viewport_size.width()) *
164      scale_factor;
165
166  return params;
167}
168
169bool UseEdgeEffectL() {
170  static bool use_edge_effect_l =
171      base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
172  return use_edge_effect_l;
173}
174
175scoped_ptr<EdgeEffectBase> CreateEdgeEffect(
176    ui::SystemUIResourceManager* resource_manager,
177    float device_scale_factor) {
178  DCHECK(resource_manager);
179  if (UseEdgeEffectL())
180    return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
181
182  return scoped_ptr<EdgeEffectBase>(
183      new EdgeEffect(resource_manager, device_scale_factor));
184}
185
186scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
187    ContentViewCore* content_view_core) {
188  DCHECK(content_view_core);
189  ui::WindowAndroidCompositor* compositor =
190      content_view_core->GetWindowAndroid()->GetCompositor();
191  DCHECK(compositor);
192  ui::SystemUIResourceManager* system_resource_manager =
193      &compositor->GetSystemUIResourceManager();
194
195  if (UseEdgeEffectL())
196    EdgeEffectL::PreloadResources(system_resource_manager);
197  else
198    EdgeEffect::PreloadResources(system_resource_manager);
199
200  return make_scoped_ptr(
201      new OverscrollGlow(base::Bind(&CreateEdgeEffect,
202                                    system_resource_manager,
203                                    content_view_core->GetDpiScale())));
204}
205
206scoped_ptr<TouchSelectionController> CreateSelectionController(
207    TouchSelectionControllerClient* client,
208    ContentViewCore* content_view_core) {
209  DCHECK(client);
210  DCHECK(content_view_core);
211  int tap_timeout_ms = gfx::ViewConfiguration::GetTapTimeoutInMs();
212  int touch_slop_pixels = gfx::ViewConfiguration::GetTouchSlopInPixels();
213  return make_scoped_ptr(new TouchSelectionController(
214      client,
215      base::TimeDelta::FromMilliseconds(tap_timeout_ms),
216      touch_slop_pixels / content_view_core->GetDpiScale()));
217}
218
219ui::GestureProvider::Config CreateGestureProviderConfig() {
220  ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
221  config.disable_click_delay =
222      base::CommandLine::ForCurrentProcess()->HasSwitch(
223          switches::kDisableClickDelay);
224  return config;
225}
226
227bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
228  return frame_metadata.min_page_scale_factor ==
229         frame_metadata.max_page_scale_factor;
230}
231
232bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
233  float window_width_dip =
234      frame_metadata.page_scale_factor *
235          frame_metadata.scrollable_viewport_size.width();
236  float content_width_css = frame_metadata.root_layer_size.width();
237  return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
238}
239
240}  // anonymous namespace
241
242ReadbackRequest::ReadbackRequest(
243    float scale,
244    SkColorType color_type,
245    gfx::Rect src_subrect,
246    const base::Callback<void(bool, const SkBitmap&)>& result_callback)
247    : scale_(scale),
248      color_type_(color_type),
249      src_subrect_(src_subrect),
250      result_callback_(result_callback) {
251}
252
253ReadbackRequest::ReadbackRequest() {
254}
255
256ReadbackRequest::~ReadbackRequest() {
257}
258
259RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
260    uint32 output_id,
261    scoped_ptr<cc::CompositorFrame> output_frame)
262    : output_surface_id(output_id), frame(output_frame.Pass()) {}
263
264RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
265
266RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
267    RenderWidgetHostImpl* widget_host,
268    ContentViewCoreImpl* content_view_core)
269    : host_(widget_host),
270      outstanding_vsync_requests_(0),
271      is_showing_(!widget_host->is_hidden()),
272      content_view_core_(NULL),
273      ime_adapter_android_(this),
274      cached_background_color_(SK_ColorWHITE),
275      last_output_surface_id_(kUndefinedOutputSurfaceId),
276      overscroll_effect_enabled_(
277          !base::CommandLine::ForCurrentProcess()->HasSwitch(
278              switches::kDisableOverscrollEdgeEffect)),
279      gesture_provider_(CreateGestureProviderConfig(), this),
280      gesture_text_selector_(this),
281      accelerated_surface_route_id_(0),
282      using_browser_compositor_(CompositorImpl::IsInitialized()),
283      frame_evictor_(new DelegatedFrameEvictor(this)),
284      locks_on_frame_count_(0),
285      observing_root_window_(false),
286      weak_ptr_factory_(this) {
287  host_->SetView(this);
288  SetContentViewCore(content_view_core);
289  ImageTransportFactoryAndroid::AddObserver(this);
290}
291
292RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
293  ImageTransportFactoryAndroid::RemoveObserver(this);
294  SetContentViewCore(NULL);
295  DCHECK(ack_callbacks_.empty());
296  DCHECK(readbacks_waiting_for_frame_.empty());
297  if (resource_collection_.get())
298    resource_collection_->SetClient(NULL);
299}
300
301
302bool RenderWidgetHostViewAndroid::OnMessageReceived(
303    const IPC::Message& message) {
304  bool handled = true;
305  IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
306    IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
307    IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
308                        OnDidChangeBodyBackgroundColor)
309    IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
310                        OnSetNeedsBeginFrame)
311    IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
312                        OnTextInputStateChanged)
313    IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
314                        OnSmartClipDataExtracted)
315    IPC_MESSAGE_UNHANDLED(handled = false)
316  IPC_END_MESSAGE_MAP()
317  return handled;
318}
319
320void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
321  NOTIMPLEMENTED();
322}
323
324void RenderWidgetHostViewAndroid::InitAsPopup(
325    RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
326  NOTIMPLEMENTED();
327}
328
329void RenderWidgetHostViewAndroid::InitAsFullscreen(
330    RenderWidgetHostView* reference_host_view) {
331  NOTIMPLEMENTED();
332}
333
334RenderWidgetHost*
335RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
336  return host_;
337}
338
339void RenderWidgetHostViewAndroid::WasShown() {
340  if (!host_ || !host_->is_hidden())
341    return;
342
343  host_->WasShown(ui::LatencyInfo());
344
345  if (content_view_core_) {
346    StartObservingRootWindow();
347    RequestVSyncUpdate(BEGIN_FRAME);
348  }
349}
350
351void RenderWidgetHostViewAndroid::WasHidden() {
352  RunAckCallbacks();
353
354  if (!host_ || host_->is_hidden())
355    return;
356
357  // Inform the renderer that we are being hidden so it can reduce its resource
358  // utilization.
359  host_->WasHidden();
360
361  StopObservingRootWindow();
362}
363
364void RenderWidgetHostViewAndroid::WasResized() {
365  host_->WasResized();
366}
367
368void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
369  // Ignore the given size as only the Java code has the power to
370  // resize the view on Android.
371  default_size_ = size;
372}
373
374void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
375  SetSize(rect.size());
376}
377
378void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
379  while (!readbacks_waiting_for_frame_.empty()) {
380    ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
381    readback_request.GetResultCallback().Run(false, SkBitmap());
382    readbacks_waiting_for_frame_.pop();
383  }
384}
385
386void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
387    float scale,
388    SkColorType color_type,
389    gfx::Rect src_subrect,
390    CopyFromCompositingSurfaceCallback& result_callback) {
391  if (!host_ || host_->is_hidden()) {
392    result_callback.Run(false, SkBitmap());
393    return;
394  }
395  if (!IsSurfaceAvailableForCopy()) {
396    // The view is visible, probably the frame has not yet arrived.
397    // Just add the ReadbackRequest to queue and wait for frame arrival
398    // to get this request processed.
399    readbacks_waiting_for_frame_.push(
400        ReadbackRequest(scale, color_type, src_subrect, result_callback));
401    return;
402  }
403
404  gfx::Size bounds = layer_->bounds();
405  if (src_subrect.IsEmpty())
406    src_subrect = gfx::Rect(bounds);
407  DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
408  DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
409  const gfx::Display& display =
410      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
411  float device_scale_factor = display.device_scale_factor();
412  DCHECK_GT(device_scale_factor, 0);
413  gfx::Size dst_size(
414      gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
415  CopyFromCompositingSurface(
416      src_subrect, dst_size, result_callback, color_type);
417}
418
419scoped_refptr<cc::DelegatedRendererLayer>
420RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
421  DCHECK(frame_provider_);
422
423  scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
424      cc::DelegatedRendererLayer::Create(frame_provider_);
425  delegated_layer->SetBounds(content_size_in_layer_);
426  delegated_layer->SetIsDrawable(true);
427  delegated_layer->SetContentsOpaque(true);
428
429  return delegated_layer;
430}
431
432bool RenderWidgetHostViewAndroid::HasValidFrame() const {
433  if (!content_view_core_)
434    return false;
435  if (!layer_)
436    return false;
437
438  if (texture_size_in_layer_.IsEmpty())
439    return false;
440  // This tell us whether a valid frame has arrived or not.
441  if (!frame_evictor_->HasFrame())
442    return false;
443
444  return true;
445}
446
447gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
448  return last_scroll_offset_;
449}
450
451gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
452  return content_view_core_->GetViewAndroid();
453}
454
455gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
456  return reinterpret_cast<gfx::NativeViewId>(
457      const_cast<RenderWidgetHostViewAndroid*>(this));
458}
459
460gfx::NativeViewAccessible
461RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
462  NOTIMPLEMENTED();
463  return NULL;
464}
465
466void RenderWidgetHostViewAndroid::MovePluginWindows(
467    const std::vector<WebPluginGeometry>& moves) {
468  // We don't have plugin windows on Android. Do nothing. Note: this is called
469  // from RenderWidgetHost::OnUpdateRect which is itself invoked while
470  // processing the corresponding message from Renderer.
471}
472
473void RenderWidgetHostViewAndroid::Focus() {
474  host_->Focus();
475  host_->SetInputMethodActive(true);
476  if (overscroll_effect_)
477    overscroll_effect_->Enable();
478}
479
480void RenderWidgetHostViewAndroid::Blur() {
481  host_->SetInputMethodActive(false);
482  host_->Blur();
483  if (overscroll_effect_)
484    overscroll_effect_->Disable();
485}
486
487bool RenderWidgetHostViewAndroid::HasFocus() const {
488  if (!content_view_core_)
489    return false;  // ContentViewCore not created yet.
490
491  return content_view_core_->HasFocus();
492}
493
494bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
495  return HasValidFrame();
496}
497
498void RenderWidgetHostViewAndroid::Show() {
499  if (is_showing_)
500    return;
501
502  is_showing_ = true;
503  if (layer_)
504    layer_->SetHideLayerAndSubtree(false);
505
506  frame_evictor_->SetVisible(true);
507  WasShown();
508}
509
510void RenderWidgetHostViewAndroid::Hide() {
511  if (!is_showing_)
512    return;
513
514  is_showing_ = false;
515  if (layer_ && locks_on_frame_count_ == 0)
516    layer_->SetHideLayerAndSubtree(true);
517
518  frame_evictor_->SetVisible(false);
519  // We don't know if we will ever get a frame if we are hiding the renderer, so
520  // we need to cancel all requests
521  AbortPendingReadbackRequests();
522  WasHidden();
523}
524
525bool RenderWidgetHostViewAndroid::IsShowing() {
526  // ContentViewCoreImpl represents the native side of the Java
527  // ContentViewCore.  It being NULL means that it is not attached
528  // to the View system yet, so we treat this RWHVA as hidden.
529  return is_showing_ && content_view_core_;
530}
531
532void RenderWidgetHostViewAndroid::LockCompositingSurface() {
533  DCHECK(HasValidFrame());
534  DCHECK(host_);
535  DCHECK(frame_evictor_->HasFrame());
536  frame_evictor_->LockFrame();
537  locks_on_frame_count_++;
538}
539
540void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
541  if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
542    return;
543
544  DCHECK(HasValidFrame());
545  frame_evictor_->UnlockFrame();
546  locks_on_frame_count_--;
547
548  if (locks_on_frame_count_ == 0) {
549    if (last_frame_info_) {
550      InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
551                                  last_frame_info_->frame.Pass());
552      last_frame_info_.reset();
553    }
554
555    if (!is_showing_ && layer_)
556      layer_->SetHideLayerAndSubtree(true);
557  }
558}
559
560void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
561    const TextSurroundingSelectionCallback& callback) {
562  // Only one outstanding request is allowed at any given time.
563  DCHECK(!callback.is_null());
564  text_surrounding_selection_callback_ = callback;
565}
566
567void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
568    const base::string16& content,
569    size_t start_offset,
570    size_t end_offset) {
571  if (text_surrounding_selection_callback_.is_null())
572    return;
573  text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
574  text_surrounding_selection_callback_.Reset();
575}
576
577void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
578  if (!frame_evictor_->HasFrame()) {
579    DCHECK_EQ(locks_on_frame_count_, 0u);
580    return;
581  }
582  while (locks_on_frame_count_ > 0) {
583    UnlockCompositingSurface();
584  }
585  RunAckCallbacks();
586}
587
588gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
589  if (!content_view_core_)
590    return gfx::Rect(default_size_);
591
592  return gfx::Rect(content_view_core_->GetViewSize());
593}
594
595gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
596  if (!content_view_core_)
597    return gfx::Size();
598
599  return content_view_core_->GetPhysicalBackingSize();
600}
601
602float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
603  if (!content_view_core_)
604    return 0.f;
605
606  // The amount that the viewport size given to Blink is shrunk by the URL-bar.
607  return content_view_core_->GetTopControlsLayoutHeightDip();
608}
609
610void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
611  // There are no cursors on Android.
612}
613
614void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
615  // Do nothing. The UI notification is handled through ContentViewClient which
616  // is TabContentsDelegate.
617}
618
619void RenderWidgetHostViewAndroid::TextInputTypeChanged(
620    ui::TextInputType type,
621    ui::TextInputMode input_mode,
622    bool can_compose_inline) {
623  // Unused on Android, which uses OnTextInputChanged instead.
624}
625
626long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
627  return reinterpret_cast<intptr_t>(&ime_adapter_android_);
628}
629
630void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
631    const ViewHostMsg_TextInputState_Params& params) {
632  if (selection_controller_) {
633    // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
634    // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
635    // while this call is present to ensure consistency with IME after
636    // navigation and tab focus changes
637    const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
638    selection_controller_->OnSelectionEditable(is_editable_node);
639  }
640
641  // If the change is not originated from IME (e.g. Javascript, autofill),
642  // send back the renderer an acknowledgement, regardless of how we exit from
643  // this method.
644  base::ScopedClosureRunner ack_caller;
645  if (params.is_non_ime_change)
646    ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
647
648  if (!IsShowing())
649    return;
650
651  content_view_core_->UpdateImeAdapter(
652      GetNativeImeAdapter(),
653      static_cast<int>(params.type), params.flags,
654      params.value, params.selection_start, params.selection_end,
655      params.composition_start, params.composition_end,
656      params.show_ime_if_needed, params.is_non_ime_change);
657}
658
659void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
660    SkColor color) {
661  if (cached_background_color_ == color)
662    return;
663
664  cached_background_color_ = color;
665  if (content_view_core_)
666    content_view_core_->OnBackgroundColorChanged(color);
667}
668
669void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
670  DCHECK(using_browser_compositor_);
671  TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
672               "enabled", enabled);
673  if (enabled)
674    RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
675  else
676    outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
677}
678
679void RenderWidgetHostViewAndroid::OnStartContentIntent(
680    const GURL& content_url) {
681  if (content_view_core_)
682    content_view_core_->StartContentIntent(content_url);
683}
684
685void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
686    const base::string16& text,
687    const base::string16& html,
688    const gfx::Rect rect) {
689  if (content_view_core_)
690    content_view_core_->OnSmartClipDataExtracted(text, html, rect);
691}
692
693bool RenderWidgetHostViewAndroid::OnTouchEvent(
694    const ui::MotionEvent& event) {
695  if (!host_)
696    return false;
697
698  if (selection_controller_ &&
699      selection_controller_->WillHandleTouchEvent(event))
700    return true;
701
702  if (!gesture_provider_.OnTouchEvent(event))
703    return false;
704
705  if (gesture_text_selector_.OnTouchEvent(event)) {
706    gesture_provider_.OnTouchEventAck(false);
707    return true;
708  }
709
710  if (host_->ShouldForwardTouchEvent()) {
711    blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event);
712    host_->ForwardTouchEventWithLatencyInfo(web_event,
713                                            CreateLatencyInfo(web_event));
714  } else {
715    const bool event_consumed = false;
716    gesture_provider_.OnTouchEventAck(event_consumed);
717  }
718
719  // Send a proactive BeginFrame on the next vsync to reduce latency.
720  // This is good enough as long as the first touch event has Begin semantics
721  // and the actual scroll happens on the next vsync.
722  if (observing_root_window_)
723    RequestVSyncUpdate(BEGIN_FRAME);
724
725  return true;
726}
727
728bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
729    const ui::MotionEvent& event) {
730  return selection_controller_ &&
731         selection_controller_->WillHandleTouchEvent(event);
732}
733
734void RenderWidgetHostViewAndroid::ResetGestureDetection() {
735  const ui::MotionEvent* current_down_event =
736      gesture_provider_.GetCurrentDownEvent();
737  if (!current_down_event)
738    return;
739
740  scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
741  DCHECK(cancel_event);
742  OnTouchEvent(*cancel_event);
743}
744
745void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
746  gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
747}
748
749void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
750    bool enabled) {
751  gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
752}
753
754void RenderWidgetHostViewAndroid::ImeCancelComposition() {
755  ime_adapter_android_.CancelComposition();
756}
757
758void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
759  ime_adapter_android_.FocusedNodeChanged(is_editable_node);
760  if (selection_controller_)
761    selection_controller_->OnSelectionEditable(is_editable_node);
762}
763
764void RenderWidgetHostViewAndroid::RenderProcessGone(
765    base::TerminationStatus status, int error_code) {
766  Destroy();
767}
768
769void RenderWidgetHostViewAndroid::Destroy() {
770  RemoveLayers();
771  SetContentViewCore(NULL);
772
773  // The RenderWidgetHost's destruction led here, so don't call it.
774  host_ = NULL;
775
776  delete this;
777}
778
779void RenderWidgetHostViewAndroid::SetTooltipText(
780    const base::string16& tooltip_text) {
781  // Tooltips don't makes sense on Android.
782}
783
784void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
785                                                   size_t offset,
786                                                   const gfx::Range& range) {
787  RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
788
789  if (selection_controller_)
790    selection_controller_->OnSelectionEmpty(text.empty());
791
792  if (!content_view_core_)
793    return;
794  if (range.is_empty()) {
795    content_view_core_->OnSelectionChanged("");
796    return;
797  }
798
799  DCHECK(!text.empty());
800  size_t pos = range.GetMin() - offset;
801  size_t n = range.length();
802
803  DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
804  if (pos >= text.length()) {
805    NOTREACHED() << "The text can not cover range.";
806    return;
807  }
808
809  std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
810
811  content_view_core_->OnSelectionChanged(utf8_selection);
812}
813
814void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
815    const ViewHostMsg_SelectionBounds_Params& params) {
816  NOTREACHED() << "Selection bounds should be routed through the compositor.";
817}
818
819void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
820  RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
821  host_->SetBackgroundOpaque(opaque);
822}
823
824void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
825    const gfx::Rect& src_subrect,
826    const gfx::Size& dst_size,
827    CopyFromCompositingSurfaceCallback& callback,
828    const SkColorType color_type) {
829  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
830  if ((!host_ || host_->is_hidden()) ||
831      !IsReadbackConfigSupported(color_type)) {
832    callback.Run(false, SkBitmap());
833    return;
834  }
835  base::TimeTicks start_time = base::TimeTicks::Now();
836  if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
837    callback.Run(false, SkBitmap());
838    return;
839  }
840  const gfx::Display& display =
841      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
842  float device_scale_factor = display.device_scale_factor();
843  gfx::Size dst_size_in_pixel =
844      ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
845  gfx::Rect src_subrect_in_pixel =
846      ConvertRectToPixel(device_scale_factor, src_subrect);
847
848  if (!using_browser_compositor_) {
849    SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
850                            color_type);
851    UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
852                        base::TimeTicks::Now() - start_time);
853    return;
854  }
855
856  scoped_ptr<cc::CopyOutputRequest> request;
857  scoped_refptr<cc::Layer> readback_layer;
858  DCHECK(content_view_core_);
859  DCHECK(content_view_core_->GetWindowAndroid());
860  ui::WindowAndroidCompositor* compositor =
861      content_view_core_->GetWindowAndroid()->GetCompositor();
862  DCHECK(compositor);
863  DCHECK(frame_provider_);
864  scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
865      CreateDelegatedLayerForFrameProvider();
866  delegated_layer->SetHideLayerAndSubtree(true);
867  compositor->AttachLayerForReadback(delegated_layer);
868
869  readback_layer = delegated_layer;
870  request = cc::CopyOutputRequest::CreateRequest(
871      base::Bind(&RenderWidgetHostViewAndroid::
872                     PrepareTextureCopyOutputResultForDelegatedReadback,
873                 dst_size_in_pixel,
874                 color_type,
875                 start_time,
876                 readback_layer,
877                 callback));
878  request->set_area(src_subrect_in_pixel);
879  readback_layer->RequestCopyOfOutput(request.Pass());
880}
881
882void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
883      const gfx::Rect& src_subrect,
884      const scoped_refptr<media::VideoFrame>& target,
885      const base::Callback<void(bool)>& callback) {
886  NOTIMPLEMENTED();
887  callback.Run(false);
888}
889
890bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
891  return false;
892}
893
894void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
895    const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
896  if (!content_view_core_)
897    return;
898
899  content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
900}
901
902scoped_ptr<SyntheticGestureTarget>
903RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
904  return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
905      host_, content_view_core_->CreateTouchEventSynthesizer()));
906}
907
908void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
909    uint32 output_surface_id) {
910  DCHECK(host_);
911  cc::CompositorFrameAck ack;
912  if (resource_collection_.get())
913    resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
914  RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
915                                                   output_surface_id,
916                                                   host_->GetProcess()->GetID(),
917                                                   ack);
918}
919
920void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
921    uint32 output_surface_id) {
922  DCHECK(resource_collection_);
923
924  cc::CompositorFrameAck ack;
925  resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
926  DCHECK(!ack.resources.empty());
927
928  RenderWidgetHostImpl::SendReclaimCompositorResources(
929      host_->GetRoutingID(),
930      output_surface_id,
931      host_->GetProcess()->GetID(),
932      ack);
933}
934
935void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
936  if (ack_callbacks_.size())
937    return;
938  SendReturnedDelegatedResources(last_output_surface_id_);
939}
940
941void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
942  RemoveLayers();
943  frame_provider_ = NULL;
944  layer_ = NULL;
945  // This gets called when ever any eviction, loosing resources, swapping
946  // problems are encountered and so we abort any pending readbacks here.
947  AbortPendingReadbackRequests();
948}
949
950void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
951    uint32 output_surface_id,
952    scoped_ptr<cc::DelegatedFrameData> frame_data) {
953  bool has_content = !texture_size_in_layer_.IsEmpty();
954
955  if (output_surface_id != last_output_surface_id_) {
956    // Drop the cc::DelegatedFrameResourceCollection so that we will not return
957    // any resources from the old output surface with the new output surface id.
958    if (resource_collection_.get()) {
959      resource_collection_->SetClient(NULL);
960      if (resource_collection_->LoseAllResources())
961        SendReturnedDelegatedResources(last_output_surface_id_);
962      resource_collection_ = NULL;
963    }
964    DestroyDelegatedContent();
965
966    last_output_surface_id_ = output_surface_id;
967  }
968
969  // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
970  // renderer frame, assuming that the browser compositor will scale
971  // it back up to device scale.  But on Android we put our browser layers in
972  // physical pixels and set our browser CC device_scale_factor to 1, so this
973  // suppresses the transform.  This line may need to be removed when fixing
974  // http://crbug.com/384134 or http://crbug.com/310763
975  frame_data->device_scale_factor = 1.0f;
976
977  if (!has_content) {
978    DestroyDelegatedContent();
979  } else {
980    if (!resource_collection_.get()) {
981      resource_collection_ = new cc::DelegatedFrameResourceCollection;
982      resource_collection_->SetClient(this);
983    }
984    if (!frame_provider_ ||
985        texture_size_in_layer_ != frame_provider_->frame_size()) {
986      RemoveLayers();
987      frame_provider_ = new cc::DelegatedFrameProvider(
988          resource_collection_.get(), frame_data.Pass());
989      layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
990      AttachLayers();
991    } else {
992      frame_provider_->SetFrameData(frame_data.Pass());
993    }
994  }
995
996  if (layer_.get()) {
997    layer_->SetIsDrawable(true);
998    layer_->SetContentsOpaque(true);
999    layer_->SetBounds(content_size_in_layer_);
1000    layer_->SetNeedsDisplay();
1001  }
1002
1003  base::Closure ack_callback =
1004      base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1005                 weak_ptr_factory_.GetWeakPtr(),
1006                 output_surface_id);
1007
1008  ack_callbacks_.push(ack_callback);
1009  if (host_->is_hidden())
1010    RunAckCallbacks();
1011}
1012
1013void RenderWidgetHostViewAndroid::ComputeContentsSize(
1014    const cc::CompositorFrameMetadata& frame_metadata) {
1015  // Calculate the content size.  This should be 0 if the texture_size is 0.
1016  gfx::Vector2dF offset;
1017  if (texture_size_in_layer_.IsEmpty())
1018    content_size_in_layer_ = gfx::Size();
1019  content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1020      frame_metadata.scrollable_viewport_size,
1021      frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1022
1023  if (overscroll_effect_) {
1024    overscroll_effect_->UpdateDisplayParameters(
1025        CreateOverscrollDisplayParameters(frame_metadata));
1026  }
1027}
1028
1029void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1030    uint32 output_surface_id,
1031    scoped_ptr<cc::CompositorFrame> frame) {
1032  last_scroll_offset_ = frame->metadata.root_scroll_offset;
1033  if (!frame->delegated_frame_data) {
1034    LOG(ERROR) << "Non-delegated renderer path no longer supported";
1035    return;
1036  }
1037
1038  if (locks_on_frame_count_ > 0) {
1039    DCHECK(HasValidFrame());
1040    RetainFrame(output_surface_id, frame.Pass());
1041    return;
1042  }
1043
1044  if (layer_ && layer_->layer_tree_host()) {
1045    for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1046      scoped_ptr<cc::SwapPromise> swap_promise(
1047          new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1048      layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1049    }
1050  }
1051
1052  DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1053
1054  cc::RenderPass* root_pass =
1055      frame->delegated_frame_data->render_pass_list.back();
1056  texture_size_in_layer_ = root_pass->output_rect.size();
1057  ComputeContentsSize(frame->metadata);
1058
1059  SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1060  frame_evictor_->SwappedFrame(!host_->is_hidden());
1061
1062  // As the metadata update may trigger view invalidation, always call it after
1063  // any potential compositor scheduling.
1064  OnFrameMetadataUpdated(frame->metadata);
1065  // Check if we have any pending readbacks, see if we have a frame available
1066  // and process them here.
1067  if (!readbacks_waiting_for_frame_.empty()) {
1068    while (!readbacks_waiting_for_frame_.empty()) {
1069      ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
1070      GetScaledContentBitmap(readback_request.GetScale(),
1071                             readback_request.GetColorFormat(),
1072                             readback_request.GetCaptureRect(),
1073                             readback_request.GetResultCallback());
1074      readbacks_waiting_for_frame_.pop();
1075    }
1076  }
1077}
1078
1079void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1080    uint32 output_surface_id,
1081    scoped_ptr<cc::CompositorFrame> frame) {
1082  InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1083}
1084
1085void RenderWidgetHostViewAndroid::RetainFrame(
1086    uint32 output_surface_id,
1087    scoped_ptr<cc::CompositorFrame> frame) {
1088  DCHECK(locks_on_frame_count_);
1089
1090  // Store the incoming frame so that it can be swapped when all the locks have
1091  // been released. If there is already a stored frame, then replace and skip
1092  // the previous one but make sure we still eventually send the ACK. Holding
1093  // the ACK also blocks the renderer when its max_frames_pending is reached.
1094  if (last_frame_info_) {
1095    base::Closure ack_callback =
1096        base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1097                   weak_ptr_factory_.GetWeakPtr(),
1098                   last_frame_info_->output_surface_id);
1099
1100    ack_callbacks_.push(ack_callback);
1101  }
1102
1103  last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1104}
1105
1106void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1107    const cc::CompositorFrameMetadata& frame_metadata) {
1108  if (!content_view_core_)
1109    return;
1110
1111  // This is a subset of OnSwapCompositorFrame() used in the synchronous
1112  // compositor flow.
1113  OnFrameMetadataUpdated(frame_metadata);
1114  ComputeContentsSize(frame_metadata);
1115
1116  // DevTools ScreenCast support for Android WebView.
1117  WebContents* web_contents = content_view_core_->GetWebContents();
1118  if (DevToolsAgentHost::HasFor(web_contents)) {
1119    scoped_refptr<DevToolsAgentHost> dtah =
1120        DevToolsAgentHost::GetOrCreateFor(web_contents);
1121    // Unblock the compositor.
1122    BrowserThread::PostTask(
1123        BrowserThread::UI, FROM_HERE,
1124        base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
1125                   static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
1126                   frame_metadata));
1127  }
1128}
1129
1130void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1131  if (layer_)
1132    layer_->SetContentsOpaque(!enabled);
1133}
1134
1135bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1136  // The synchronous (WebView) compositor does not have a proper browser
1137  // compositor with which to drive animations.
1138  return using_browser_compositor_;
1139}
1140
1141void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1142  DCHECK(content_view_core_);
1143  DCHECK(using_browser_compositor_);
1144  content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1145}
1146
1147void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1148  MoveCaret(gfx::Point(position.x(), position.y()));
1149}
1150
1151void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1152    const gfx::PointF& start,
1153    const gfx::PointF& end) {
1154  DCHECK(content_view_core_);
1155  content_view_core_->SelectBetweenCoordinates(start, end);
1156}
1157
1158void RenderWidgetHostViewAndroid::OnSelectionEvent(
1159    SelectionEventType event,
1160    const gfx::PointF& position) {
1161  DCHECK(content_view_core_);
1162  content_view_core_->OnSelectionEvent(event, position);
1163}
1164
1165scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
1166  DCHECK(content_view_core_);
1167  if (!using_browser_compositor_)
1168    return content_view_core_->CreatePopupTouchHandleDrawable();
1169
1170  return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1171      content_view_core_->GetLayer(),
1172      content_view_core_->GetDpiScale(),
1173      base::android::GetApplicationContext()));
1174}
1175
1176void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1177    const gfx::Rect& src_subrect_in_pixel,
1178    const gfx::Size& dst_size_in_pixel,
1179    const base::Callback<void(bool, const SkBitmap&)>& callback,
1180    const SkColorType color_type) {
1181  SynchronousCompositor* compositor =
1182      SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1183                                        host_->GetRoutingID());
1184  if (!compositor) {
1185    callback.Run(false, SkBitmap());
1186    return;
1187  }
1188
1189  SkBitmap bitmap;
1190  bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1191                                       dst_size_in_pixel.height(),
1192                                       color_type,
1193                                       kPremul_SkAlphaType));
1194  SkCanvas canvas(bitmap);
1195  canvas.scale(
1196      (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
1197      (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
1198  compositor->DemandDrawSw(&canvas);
1199  callback.Run(true, bitmap);
1200}
1201
1202void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1203    const cc::CompositorFrameMetadata& frame_metadata) {
1204
1205  // Disable double tap zoom for pages that have a width=device-width or
1206  // narrower viewport (indicating that this is a mobile-optimized or responsive
1207  // web design, so text will be legible without zooming). Also disable
1208  // double tap and pinch for pages that prevent zooming in or out.
1209  bool has_mobile_viewport = HasMobileViewport(frame_metadata);
1210  bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
1211  gesture_provider_.SetDoubleTapSupportForPageEnabled(
1212      !has_fixed_page_scale && !has_mobile_viewport);
1213
1214  if (!content_view_core_)
1215    return;
1216
1217  if (selection_controller_) {
1218    selection_controller_->OnSelectionBoundsChanged(
1219        frame_metadata.selection_start, frame_metadata.selection_end);
1220  }
1221
1222  // All offsets and sizes are in CSS pixels.
1223  content_view_core_->UpdateFrameInfo(
1224      frame_metadata.root_scroll_offset,
1225      frame_metadata.page_scale_factor,
1226      gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1227                     frame_metadata.max_page_scale_factor),
1228      frame_metadata.root_layer_size,
1229      frame_metadata.scrollable_viewport_size,
1230      frame_metadata.location_bar_offset,
1231      frame_metadata.location_bar_content_translation);
1232#if defined(VIDEO_HOLE)
1233  if (host_ && host_->IsRenderView()) {
1234    RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1235        RenderViewHost::From(host_));
1236    rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
1237  }
1238#endif  // defined(VIDEO_HOLE)
1239}
1240
1241void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
1242                                                                int route_id) {
1243  accelerated_surface_route_id_ = route_id;
1244}
1245
1246void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
1247    const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1248    int gpu_host_id) {
1249  NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
1250}
1251
1252void RenderWidgetHostViewAndroid::AttachLayers() {
1253  if (!content_view_core_)
1254    return;
1255  if (!layer_.get())
1256    return;
1257
1258  content_view_core_->AttachLayer(layer_);
1259  if (overscroll_effect_)
1260    overscroll_effect_->Enable();
1261  layer_->SetHideLayerAndSubtree(!is_showing_);
1262}
1263
1264void RenderWidgetHostViewAndroid::RemoveLayers() {
1265  if (!content_view_core_)
1266    return;
1267
1268  if (!layer_.get())
1269    return;
1270
1271  content_view_core_->RemoveLayer(layer_);
1272  if (overscroll_effect_)
1273    overscroll_effect_->Disable();
1274}
1275
1276void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1277  // The synchronous compositor does not requre BeginFrame messages.
1278  if (!using_browser_compositor_)
1279    requests &= FLUSH_INPUT;
1280
1281  bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1282  outstanding_vsync_requests_ |= requests;
1283  // Note that if we're not currently observing the root window, outstanding
1284  // vsync requests will be pushed if/when we resume observing in
1285  // |StartObservingRootWindow()|.
1286  if (observing_root_window_ && should_request_vsync)
1287    content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1288}
1289
1290void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1291  DCHECK(content_view_core_);
1292  if (observing_root_window_)
1293    return;
1294
1295  observing_root_window_ = true;
1296  content_view_core_->GetWindowAndroid()->AddObserver(this);
1297
1298  // Clear existing vsync requests to allow a request to the new window.
1299  uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1300  outstanding_vsync_requests_ = 0;
1301  RequestVSyncUpdate(outstanding_vsync_requests);
1302}
1303
1304void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1305  if (!content_view_core_) {
1306    DCHECK(!observing_root_window_);
1307    return;
1308  }
1309
1310  if (!observing_root_window_)
1311    return;
1312
1313  observing_root_window_ = false;
1314  content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1315}
1316
1317void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1318                                                 base::TimeDelta vsync_period) {
1319  TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1320               "frame_time_us", frame_time.ToInternalValue());
1321  base::TimeTicks display_time = frame_time + vsync_period;
1322
1323  // TODO(brianderson): Use adaptive draw-time estimation.
1324  base::TimeDelta estimated_browser_composite_time =
1325      base::TimeDelta::FromMicroseconds(
1326          (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
1327
1328  base::TimeTicks deadline = display_time - estimated_browser_composite_time;
1329
1330  host_->Send(new ViewMsg_BeginFrame(
1331      host_->GetRoutingID(),
1332      cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
1333}
1334
1335bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1336  bool needs_animate =
1337      overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
1338  if (selection_controller_)
1339    needs_animate |= selection_controller_->Animate(frame_time);
1340  return needs_animate;
1341}
1342
1343void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
1344    const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
1345    int gpu_host_id) {
1346  NOTREACHED();
1347}
1348
1349void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
1350  NOTREACHED();
1351}
1352
1353void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
1354  NOTREACHED();
1355}
1356
1357void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1358  if (layer_.get())
1359    DestroyDelegatedContent();
1360  frame_evictor_->DiscardedFrame();
1361  // We are evicting the delegated frame,
1362  // so there should be no pending readback requests
1363  DCHECK(readbacks_waiting_for_frame_.empty());
1364}
1365
1366bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1367    const gfx::Size& desired_size) {
1368  NOTREACHED();
1369  return false;
1370}
1371
1372void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1373  // ScreenInfo isn't tied to the widget on Android. Always return the default.
1374  RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1375}
1376
1377// TODO(jrg): Find out the implications and answer correctly here,
1378// as we are returning the WebView and not root window bounds.
1379gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1380  return GetViewBounds();
1381}
1382
1383gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1384  gfx::GLSurfaceHandle handle =
1385      gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
1386  if (using_browser_compositor_) {
1387    handle.parent_client_id =
1388        ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
1389  }
1390  return handle;
1391}
1392
1393void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1394    const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1395  const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1396  gesture_provider_.OnTouchEventAck(event_consumed);
1397}
1398
1399void RenderWidgetHostViewAndroid::GestureEventAck(
1400    const blink::WebGestureEvent& event,
1401    InputEventAckState ack_result) {
1402  // The overscroll effect requires an explicit release signal that may not be
1403  // sent from the renderer compositor.
1404  if (event.type == blink::WebInputEvent::GestureScrollEnd ||
1405      event.type == blink::WebInputEvent::GestureFlingStart) {
1406    DidOverscroll(DidOverscrollParams());
1407  }
1408
1409  if (content_view_core_)
1410    content_view_core_->OnGestureEventAck(event, ack_result);
1411}
1412
1413InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1414    const blink::WebInputEvent& input_event) {
1415  if (selection_controller_) {
1416    switch (input_event.type) {
1417      case blink::WebInputEvent::GestureLongPress:
1418        selection_controller_->OnLongPressEvent();
1419        break;
1420      case blink::WebInputEvent::GestureTap:
1421        selection_controller_->OnTapEvent();
1422        break;
1423      default:
1424        break;
1425    }
1426  }
1427
1428  if (content_view_core_ &&
1429      content_view_core_->FilterInputEvent(input_event))
1430    return INPUT_EVENT_ACK_STATE_CONSUMED;
1431
1432  if (!host_)
1433    return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1434
1435  if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1436      input_event.type == blink::WebInputEvent::TouchStart) {
1437    GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1438    GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1439    if (shim && gpu_data && accelerated_surface_route_id_ &&
1440        gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1441      shim->Send(
1442          new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1443  }
1444
1445  SynchronousCompositorImpl* compositor =
1446      SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1447                                          host_->GetRoutingID());
1448  if (compositor)
1449    return compositor->HandleInputEvent(input_event);
1450  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1451}
1452
1453void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1454  TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1455  RequestVSyncUpdate(FLUSH_INPUT);
1456}
1457
1458BrowserAccessibilityManager*
1459    RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1460        BrowserAccessibilityDelegate* delegate) {
1461  // TODO(dmazzoni): Currently there can only be one
1462  // BrowserAccessibilityManager per ContentViewCore, so return NULL
1463  // if there's already a BrowserAccessibilityManager for the main
1464  // frame.  Eventually, in order to support cross-process iframes on
1465  // Android we'll need to add support for a
1466  // BrowserAccessibilityManager for a child frame.
1467  // http://crbug.com/423846
1468  if (!host_ || host_->GetRootBrowserAccessibilityManager())
1469    return NULL;
1470
1471  base::android::ScopedJavaLocalRef<jobject> obj;
1472  if (content_view_core_)
1473    obj = content_view_core_->GetJavaObject();
1474  return new BrowserAccessibilityManagerAndroid(
1475      obj,
1476      BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1477      delegate);
1478}
1479
1480bool RenderWidgetHostViewAndroid::LockMouse() {
1481  NOTIMPLEMENTED();
1482  return false;
1483}
1484
1485void RenderWidgetHostViewAndroid::UnlockMouse() {
1486  NOTIMPLEMENTED();
1487}
1488
1489// Methods called from the host to the render
1490
1491void RenderWidgetHostViewAndroid::SendKeyEvent(
1492    const NativeWebKeyboardEvent& event) {
1493  if (host_)
1494    host_->ForwardKeyboardEvent(event);
1495}
1496
1497void RenderWidgetHostViewAndroid::SendMouseEvent(
1498    const blink::WebMouseEvent& event) {
1499  if (host_)
1500    host_->ForwardMouseEvent(event);
1501}
1502
1503void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1504    const blink::WebMouseWheelEvent& event) {
1505  if (host_)
1506    host_->ForwardWheelEvent(event);
1507}
1508
1509void RenderWidgetHostViewAndroid::SendGestureEvent(
1510    const blink::WebGestureEvent& event) {
1511  // Sending a gesture that may trigger overscroll should resume the effect.
1512  if (overscroll_effect_)
1513    overscroll_effect_->Enable();
1514
1515  if (host_)
1516    host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1517}
1518
1519void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1520  if (host_)
1521    host_->MoveCaret(point);
1522}
1523
1524void RenderWidgetHostViewAndroid::DismissTextHandles() {
1525  if (selection_controller_)
1526    selection_controller_->HideAndDisallowShowingAutomatically();
1527}
1528
1529void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
1530  if (selection_controller_)
1531    selection_controller_->SetTemporarilyHidden(hidden);
1532}
1533
1534void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1535    const gfx::PointF& point) {
1536  if (!selection_controller_)
1537    return;
1538
1539  // As the paste popup may be triggered *before* the bounds and editability
1540  // of the region have been updated, explicitly set the properties now.
1541  // TODO(jdduke): Remove this workaround when auxiliary paste popup
1542  // notifications are no longer required, crbug.com/398170.
1543  cc::ViewportSelectionBound insertion_bound;
1544  insertion_bound.type = cc::SELECTION_BOUND_CENTER;
1545  insertion_bound.visible = true;
1546  insertion_bound.edge_top = point;
1547  insertion_bound.edge_bottom = point;
1548  DismissTextHandles();
1549  ShowSelectionHandlesAutomatically();
1550  selection_controller_->OnSelectionEditable(true);
1551  selection_controller_->OnSelectionEmpty(true);
1552  selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1553                                                  insertion_bound);
1554}
1555
1556SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1557  return cached_background_color_;
1558}
1559
1560void RenderWidgetHostViewAndroid::DidOverscroll(
1561    const DidOverscrollParams& params) {
1562  if (!content_view_core_ || !layer_ || !is_showing_)
1563    return;
1564
1565  const float device_scale_factor = content_view_core_->GetDpiScale();
1566
1567  if (overscroll_effect_ &&
1568      overscroll_effect_->OnOverscrolled(
1569          content_view_core_->GetLayer(),
1570          base::TimeTicks::Now(),
1571          gfx::ScaleVector2d(params.accumulated_overscroll,
1572                             device_scale_factor),
1573          gfx::ScaleVector2d(params.latest_overscroll_delta,
1574                             device_scale_factor),
1575          gfx::ScaleVector2d(params.current_fling_velocity,
1576                             device_scale_factor),
1577          gfx::ScaleVector2d(
1578              params.causal_event_viewport_point.OffsetFromOrigin(),
1579              device_scale_factor))) {
1580    SetNeedsAnimate();
1581  }
1582}
1583
1584void RenderWidgetHostViewAndroid::DidStopFlinging() {
1585  if (content_view_core_)
1586    content_view_core_->DidStopFlinging();
1587}
1588
1589void RenderWidgetHostViewAndroid::SetContentViewCore(
1590    ContentViewCoreImpl* content_view_core) {
1591  RemoveLayers();
1592  StopObservingRootWindow();
1593
1594  bool resize = false;
1595  if (content_view_core != content_view_core_) {
1596    overscroll_effect_.reset();
1597    selection_controller_.reset();
1598    ReleaseLocksOnSurface();
1599    resize = true;
1600  }
1601
1602  content_view_core_ = content_view_core;
1603
1604  BrowserAccessibilityManager* manager = NULL;
1605  if (host_)
1606    manager = host_->GetRootBrowserAccessibilityManager();
1607  if (manager) {
1608    base::android::ScopedJavaLocalRef<jobject> obj;
1609    if (content_view_core_)
1610      obj = content_view_core_->GetJavaObject();
1611    manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1612  }
1613
1614  AttachLayers();
1615
1616  if (!content_view_core_)
1617    return;
1618
1619  StartObservingRootWindow();
1620
1621  if (resize)
1622    WasResized();
1623
1624  if (!selection_controller_)
1625    selection_controller_ = CreateSelectionController(this, content_view_core_);
1626
1627  if (overscroll_effect_enabled_ && !overscroll_effect_ &&
1628      content_view_core_->GetWindowAndroid()->GetCompositor())
1629    overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1630}
1631
1632void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1633  while (!ack_callbacks_.empty()) {
1634    ack_callbacks_.front().Run();
1635    ack_callbacks_.pop();
1636  }
1637}
1638
1639void RenderWidgetHostViewAndroid::OnGestureEvent(
1640    const ui::GestureEventData& gesture) {
1641  if (gesture_text_selector_.OnGestureEvent(gesture))
1642    return;
1643
1644  SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
1645}
1646
1647void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1648  RunAckCallbacks();
1649}
1650
1651
1652void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1653  DCHECK(content_view_core_);
1654  if (overscroll_effect_enabled_ && !overscroll_effect_)
1655    overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1656}
1657
1658void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1659  DCHECK(content_view_core_);
1660  DCHECK(using_browser_compositor_);
1661  RunAckCallbacks();
1662  overscroll_effect_.reset();
1663}
1664
1665void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1666                                          base::TimeDelta vsync_period) {
1667  TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1668  if (!host_)
1669    return;
1670
1671  const uint32 current_vsync_requests = outstanding_vsync_requests_;
1672  outstanding_vsync_requests_ = 0;
1673
1674  if (current_vsync_requests & FLUSH_INPUT)
1675    host_->FlushInput();
1676
1677  if (current_vsync_requests & BEGIN_FRAME ||
1678      current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
1679    SendBeginFrame(frame_time, vsync_period);
1680  }
1681
1682  if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
1683    RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
1684}
1685
1686void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1687  if (Animate(begin_frame_time))
1688    SetNeedsAnimate();
1689}
1690
1691void RenderWidgetHostViewAndroid::OnLostResources() {
1692  ReleaseLocksOnSurface();
1693  if (layer_.get())
1694    DestroyDelegatedContent();
1695  DCHECK(ack_callbacks_.empty());
1696  // We should not loose a frame if we have readback requests pending.
1697  DCHECK(readbacks_waiting_for_frame_.empty());
1698}
1699
1700// static
1701void
1702RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1703    const gfx::Size& dst_size_in_pixel,
1704    const SkColorType color_type,
1705    const base::TimeTicks& start_time,
1706    scoped_refptr<cc::Layer> readback_layer,
1707    const base::Callback<void(bool, const SkBitmap&)>& callback,
1708    scoped_ptr<cc::CopyOutputResult> result) {
1709  readback_layer->RemoveFromParent();
1710  PrepareTextureCopyOutputResult(
1711      dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1712}
1713
1714// static
1715void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1716    const gfx::Size& dst_size_in_pixel,
1717    const SkColorType color_type,
1718    const base::TimeTicks& start_time,
1719    const base::Callback<void(bool, const SkBitmap&)>& callback,
1720    scoped_ptr<cc::CopyOutputResult> result) {
1721  base::ScopedClosureRunner scoped_callback_runner(
1722      base::Bind(callback, false, SkBitmap()));
1723  TRACE_EVENT0("cc",
1724               "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1725
1726  if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1727    return;
1728
1729  scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1730  if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1731                                                dst_size_in_pixel.height(),
1732                                                color_type,
1733                                                kOpaque_SkAlphaType)))
1734    return;
1735
1736  ImageTransportFactoryAndroid* factory =
1737      ImageTransportFactoryAndroid::GetInstance();
1738  GLHelper* gl_helper = factory->GetGLHelper();
1739
1740  if (!gl_helper)
1741    return;
1742
1743  scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1744      new SkAutoLockPixels(*bitmap));
1745  uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1746
1747  cc::TextureMailbox texture_mailbox;
1748  scoped_ptr<cc::SingleReleaseCallback> release_callback;
1749  result->TakeTexture(&texture_mailbox, &release_callback);
1750  DCHECK(texture_mailbox.IsTexture());
1751  if (!texture_mailbox.IsTexture())
1752    return;
1753
1754  ignore_result(scoped_callback_runner.Release());
1755
1756  gl_helper->CropScaleReadbackAndCleanMailbox(
1757      texture_mailbox.mailbox(),
1758      texture_mailbox.sync_point(),
1759      result->size(),
1760      gfx::Rect(result->size()),
1761      dst_size_in_pixel,
1762      pixels,
1763      color_type,
1764      base::Bind(&CopyFromCompositingSurfaceFinished,
1765                 callback,
1766                 base::Passed(&release_callback),
1767                 base::Passed(&bitmap),
1768                 start_time,
1769                 base::Passed(&bitmap_pixels_lock)),
1770      GLHelper::SCALER_QUALITY_GOOD);
1771}
1772
1773bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1774    SkColorType color_type) {
1775  ImageTransportFactoryAndroid* factory =
1776      ImageTransportFactoryAndroid::GetInstance();
1777  GLHelper* gl_helper = factory->GetGLHelper();
1778  if (!gl_helper)
1779    return false;
1780  return gl_helper->IsReadbackConfigSupported(color_type);
1781}
1782
1783SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1784  // Define the criteria here. If say the 16 texture readback is
1785  // supported we should go with that (this degrades quality)
1786  // or stick back to the default format.
1787  if (base::SysInfo::IsLowEndDevice()) {
1788    if (IsReadbackConfigSupported(kRGB_565_SkColorType))
1789      return kRGB_565_SkColorType;
1790  }
1791  return kN32_SkColorType;
1792}
1793
1794void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1795  // Fake a long press to allow automatic selection handle showing.
1796  if (selection_controller_)
1797    selection_controller_->OnLongPressEvent();
1798}
1799
1800void RenderWidgetHostViewAndroid::SelectRange(
1801    float x1, float y1, float x2, float y2) {
1802  if (content_view_core_)
1803    static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
1804        SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
1805}
1806
1807void RenderWidgetHostViewAndroid::Unselect() {
1808  if (content_view_core_)
1809    content_view_core_->GetWebContents()->Unselect();
1810}
1811
1812void RenderWidgetHostViewAndroid::LongPress(
1813    base::TimeTicks time, float x, float y) {
1814  blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
1815      blink::WebInputEvent::GestureLongPress,
1816      (time - base::TimeTicks()).InSecondsF(), x, y);
1817  SendGestureEvent(long_press);
1818}
1819
1820// static
1821void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1822    blink::WebScreenInfo* results) {
1823  const gfx::Display& display =
1824      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1825  results->rect = display.bounds();
1826  // TODO(husky): Remove any system controls from availableRect.
1827  results->availableRect = display.work_area();
1828  results->deviceScaleFactor = display.device_scale_factor();
1829  results->orientationAngle = display.RotationAsDegree();
1830  results->orientationType =
1831      RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
1832  gfx::DeviceDisplayInfo info;
1833  results->depth = info.GetBitsPerPixel();
1834  results->depthPerComponent = info.GetBitsPerComponent();
1835  results->isMonochrome = (results->depthPerComponent == 0);
1836}
1837
1838} // namespace content
1839