cc: Make picture pile base thread safe.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blob32d0c022837e4fb27307ab3f99d7952f32369550
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.
5 #include "content/browser/renderer_host/render_widget_host_view_android.h"
7 #include <android/bitmap.h>
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_provider_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"
80 namespace content {
82 namespace {
84 const int kUndefinedOutputSurfaceId = -1;
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.
89 const float kMobileViewportWidthEpsilon = 0.15f;
91 // Used for conditional creation of EdgeEffect types for overscroll.
92 const int kKitKatMR2SDKVersion = 19;
94 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
96 // Sends an acknowledgement to the renderer of a processed IME event.
97 void SendImeEventAck(RenderWidgetHostImpl* host) {
98 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
101 void 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();
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);
124 ui::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,
134 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
137 return latency_info;
140 OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
141 const cc::CompositorFrameMetadata& frame_metadata) {
142 const float scale_factor =
143 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
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;
166 return params;
169 bool UseEdgeEffectL() {
170 static bool use_edge_effect_l =
171 base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
172 return use_edge_effect_l;
175 scoped_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));
182 return scoped_ptr<EdgeEffectBase>(
183 new EdgeEffect(resource_manager, device_scale_factor));
186 scoped_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();
195 if (UseEdgeEffectL())
196 EdgeEffectL::PreloadResources(system_resource_manager);
197 else
198 EdgeEffect::PreloadResources(system_resource_manager);
200 return make_scoped_ptr(
201 new OverscrollGlow(base::Bind(&CreateEdgeEffect,
202 system_resource_manager,
203 content_view_core->GetDpiScale())));
206 scoped_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()));
219 ui::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;
227 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
228 return frame_metadata.min_page_scale_factor ==
229 frame_metadata.max_page_scale_factor;
232 bool 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;
240 } // anonymous namespace
242 ReadbackRequest::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) {
253 ReadbackRequest::ReadbackRequest() {
256 ReadbackRequest::~ReadbackRequest() {
259 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
260 uint32 output_id,
261 scoped_ptr<cc::CompositorFrame> output_frame)
262 : output_surface_id(output_id), frame(output_frame.Pass()) {}
264 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
266 RenderWidgetHostViewAndroid::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_synchronous_compositor_(SynchronousCompositorImpl::FromID(
283 widget_host->GetProcess()->GetID(),
284 widget_host->GetRoutingID()) != NULL),
285 frame_evictor_(new DelegatedFrameEvictor(this)),
286 locks_on_frame_count_(0),
287 observing_root_window_(false),
288 weak_ptr_factory_(this) {
289 host_->SetView(this);
290 SetContentViewCore(content_view_core);
291 ImageTransportFactoryAndroid::AddObserver(this);
294 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
295 ImageTransportFactoryAndroid::RemoveObserver(this);
296 SetContentViewCore(NULL);
297 DCHECK(ack_callbacks_.empty());
298 DCHECK(readbacks_waiting_for_frame_.empty());
299 if (resource_collection_.get())
300 resource_collection_->SetClient(NULL);
304 bool RenderWidgetHostViewAndroid::OnMessageReceived(
305 const IPC::Message& message) {
306 bool handled = true;
307 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
308 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
309 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
310 OnDidChangeBodyBackgroundColor)
311 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
312 OnSetNeedsBeginFrame)
313 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
314 OnTextInputStateChanged)
315 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
316 OnSmartClipDataExtracted)
317 IPC_MESSAGE_UNHANDLED(handled = false)
318 IPC_END_MESSAGE_MAP()
319 return handled;
322 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
323 NOTIMPLEMENTED();
326 void RenderWidgetHostViewAndroid::InitAsPopup(
327 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
328 NOTIMPLEMENTED();
331 void RenderWidgetHostViewAndroid::InitAsFullscreen(
332 RenderWidgetHostView* reference_host_view) {
333 NOTIMPLEMENTED();
336 RenderWidgetHost*
337 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
338 return host_;
341 void RenderWidgetHostViewAndroid::WasShown() {
342 if (!host_ || !host_->is_hidden())
343 return;
345 host_->WasShown(ui::LatencyInfo());
347 if (content_view_core_) {
348 StartObservingRootWindow();
349 RequestVSyncUpdate(BEGIN_FRAME);
353 void RenderWidgetHostViewAndroid::WasHidden() {
354 RunAckCallbacks();
356 if (!host_ || host_->is_hidden())
357 return;
359 // Inform the renderer that we are being hidden so it can reduce its resource
360 // utilization.
361 host_->WasHidden();
363 StopObservingRootWindow();
366 void RenderWidgetHostViewAndroid::WasResized() {
367 host_->WasResized();
370 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
371 // Ignore the given size as only the Java code has the power to
372 // resize the view on Android.
373 default_size_ = size;
376 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
377 SetSize(rect.size());
380 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
381 while (!readbacks_waiting_for_frame_.empty()) {
382 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
383 readback_request.GetResultCallback().Run(false, SkBitmap());
384 readbacks_waiting_for_frame_.pop();
388 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
389 float scale,
390 SkColorType color_type,
391 gfx::Rect src_subrect,
392 CopyFromCompositingSurfaceCallback& result_callback) {
393 if (!host_ || host_->is_hidden()) {
394 result_callback.Run(false, SkBitmap());
395 return;
397 if (!IsSurfaceAvailableForCopy()) {
398 // The view is visible, probably the frame has not yet arrived.
399 // Just add the ReadbackRequest to queue and wait for frame arrival
400 // to get this request processed.
401 readbacks_waiting_for_frame_.push(
402 ReadbackRequest(scale, color_type, src_subrect, result_callback));
403 return;
406 gfx::Size bounds = layer_->bounds();
407 if (src_subrect.IsEmpty())
408 src_subrect = gfx::Rect(bounds);
409 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
410 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
411 const gfx::Display& display =
412 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
413 float device_scale_factor = display.device_scale_factor();
414 DCHECK_GT(device_scale_factor, 0);
415 gfx::Size dst_size(
416 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
417 CopyFromCompositingSurface(
418 src_subrect, dst_size, result_callback, color_type);
421 scoped_refptr<cc::DelegatedRendererLayer>
422 RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
423 DCHECK(frame_provider_.get());
425 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
426 cc::DelegatedRendererLayer::Create(frame_provider_);
427 delegated_layer->SetBounds(content_size_in_layer_);
428 delegated_layer->SetIsDrawable(true);
429 delegated_layer->SetContentsOpaque(true);
431 return delegated_layer;
434 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
435 if (!content_view_core_)
436 return false;
437 if (!layer_.get())
438 return false;
440 if (texture_size_in_layer_.IsEmpty())
441 return false;
442 // This tell us whether a valid frame has arrived or not.
443 if (!frame_evictor_->HasFrame())
444 return false;
446 return true;
449 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
450 return last_scroll_offset_;
453 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
454 return content_view_core_->GetViewAndroid();
457 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
458 return reinterpret_cast<gfx::NativeViewId>(
459 const_cast<RenderWidgetHostViewAndroid*>(this));
462 gfx::NativeViewAccessible
463 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
464 NOTIMPLEMENTED();
465 return NULL;
468 void RenderWidgetHostViewAndroid::MovePluginWindows(
469 const std::vector<WebPluginGeometry>& moves) {
470 // We don't have plugin windows on Android. Do nothing. Note: this is called
471 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
472 // processing the corresponding message from Renderer.
475 void RenderWidgetHostViewAndroid::Focus() {
476 host_->Focus();
477 host_->SetInputMethodActive(true);
478 if (overscroll_effect_)
479 overscroll_effect_->Enable();
480 if (selection_controller_)
481 selection_controller_->SetTemporarilyHidden(false);
484 void RenderWidgetHostViewAndroid::Blur() {
485 host_->SetInputMethodActive(false);
486 host_->Blur();
487 if (overscroll_effect_)
488 overscroll_effect_->Disable();
489 if (selection_controller_)
490 selection_controller_->SetTemporarilyHidden(true);
493 bool RenderWidgetHostViewAndroid::HasFocus() const {
494 if (!content_view_core_)
495 return false; // ContentViewCore not created yet.
497 return content_view_core_->HasFocus();
500 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
501 return HasValidFrame();
504 void RenderWidgetHostViewAndroid::Show() {
505 if (is_showing_)
506 return;
508 is_showing_ = true;
509 if (layer_.get())
510 layer_->SetHideLayerAndSubtree(false);
512 frame_evictor_->SetVisible(true);
513 WasShown();
516 void RenderWidgetHostViewAndroid::Hide() {
517 if (!is_showing_)
518 return;
520 is_showing_ = false;
521 if (layer_.get() && locks_on_frame_count_ == 0)
522 layer_->SetHideLayerAndSubtree(true);
524 frame_evictor_->SetVisible(false);
525 // We don't know if we will ever get a frame if we are hiding the renderer, so
526 // we need to cancel all requests
527 AbortPendingReadbackRequests();
528 WasHidden();
531 bool RenderWidgetHostViewAndroid::IsShowing() {
532 // ContentViewCoreImpl represents the native side of the Java
533 // ContentViewCore. It being NULL means that it is not attached
534 // to the View system yet, so we treat this RWHVA as hidden.
535 return is_showing_ && content_view_core_;
538 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
539 DCHECK(HasValidFrame());
540 DCHECK(host_);
541 DCHECK(frame_evictor_->HasFrame());
542 frame_evictor_->LockFrame();
543 locks_on_frame_count_++;
546 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
547 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
548 return;
550 DCHECK(HasValidFrame());
551 frame_evictor_->UnlockFrame();
552 locks_on_frame_count_--;
554 if (locks_on_frame_count_ == 0) {
555 if (last_frame_info_) {
556 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
557 last_frame_info_->frame.Pass());
558 last_frame_info_.reset();
561 if (!is_showing_ && layer_.get())
562 layer_->SetHideLayerAndSubtree(true);
566 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
567 const TextSurroundingSelectionCallback& callback) {
568 // Only one outstanding request is allowed at any given time.
569 DCHECK(!callback.is_null());
570 text_surrounding_selection_callback_ = callback;
573 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
574 const base::string16& content,
575 size_t start_offset,
576 size_t end_offset) {
577 if (text_surrounding_selection_callback_.is_null())
578 return;
579 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
580 text_surrounding_selection_callback_.Reset();
583 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
584 if (!frame_evictor_->HasFrame()) {
585 DCHECK_EQ(locks_on_frame_count_, 0u);
586 return;
588 while (locks_on_frame_count_ > 0) {
589 UnlockCompositingSurface();
591 RunAckCallbacks();
594 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
595 if (!content_view_core_)
596 return gfx::Rect(default_size_);
598 return gfx::Rect(content_view_core_->GetViewSize());
601 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
602 if (!content_view_core_)
603 return gfx::Size();
605 return content_view_core_->GetPhysicalBackingSize();
608 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
609 if (!content_view_core_)
610 return 0.f;
612 // The amount that the viewport size given to Blink is shrunk by the URL-bar.
613 return content_view_core_->GetTopControlsLayoutHeightDip();
616 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
617 // There are no cursors on Android.
620 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
621 // Do nothing. The UI notification is handled through ContentViewClient which
622 // is TabContentsDelegate.
625 void RenderWidgetHostViewAndroid::TextInputTypeChanged(
626 ui::TextInputType type,
627 ui::TextInputMode input_mode,
628 bool can_compose_inline,
629 int flags) {
630 // Unused on Android, which uses OnTextInputChanged instead.
633 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
634 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
637 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
638 const ViewHostMsg_TextInputState_Params& params) {
639 if (selection_controller_) {
640 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
641 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
642 // while this call is present to ensure consistency with IME after
643 // navigation and tab focus changes
644 const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
645 selection_controller_->OnSelectionEditable(is_editable_node);
648 // If the change is not originated from IME (e.g. Javascript, autofill),
649 // send back the renderer an acknowledgement, regardless of how we exit from
650 // this method.
651 base::ScopedClosureRunner ack_caller;
652 if (params.is_non_ime_change)
653 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
655 if (!IsShowing())
656 return;
658 content_view_core_->UpdateImeAdapter(
659 GetNativeImeAdapter(),
660 static_cast<int>(params.type), params.flags,
661 params.value, params.selection_start, params.selection_end,
662 params.composition_start, params.composition_end,
663 params.show_ime_if_needed, params.is_non_ime_change);
666 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
667 SkColor color) {
668 if (cached_background_color_ == color)
669 return;
671 cached_background_color_ = color;
672 if (content_view_core_)
673 content_view_core_->OnBackgroundColorChanged(color);
676 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
677 DCHECK(!using_synchronous_compositor_);
678 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
679 "enabled", enabled);
680 if (enabled)
681 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
682 else
683 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
686 void RenderWidgetHostViewAndroid::OnStartContentIntent(
687 const GURL& content_url) {
688 if (content_view_core_)
689 content_view_core_->StartContentIntent(content_url);
692 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
693 const base::string16& text,
694 const base::string16& html,
695 const gfx::Rect rect) {
696 if (content_view_core_)
697 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
700 bool RenderWidgetHostViewAndroid::OnTouchEvent(
701 const ui::MotionEvent& event) {
702 if (!host_)
703 return false;
705 if (selection_controller_ &&
706 selection_controller_->WillHandleTouchEvent(event))
707 return true;
709 if (gesture_text_selector_.OnTouchEvent(event))
710 return true;
712 if (!gesture_provider_.OnTouchEvent(event))
713 return false;
715 if (host_->ShouldForwardTouchEvent()) {
716 blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event);
717 host_->ForwardTouchEventWithLatencyInfo(web_event,
718 CreateLatencyInfo(web_event));
719 } else {
720 const bool event_consumed = false;
721 gesture_provider_.OnTouchEventAck(event_consumed);
724 // Send a proactive BeginFrame on the next vsync to reduce latency.
725 // This is good enough as long as the first touch event has Begin semantics
726 // and the actual scroll happens on the next vsync.
727 if (observing_root_window_)
728 RequestVSyncUpdate(BEGIN_FRAME);
730 return true;
733 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
734 const ui::MotionEvent& event) {
735 return selection_controller_ &&
736 selection_controller_->WillHandleTouchEvent(event);
739 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
740 const ui::MotionEvent* current_down_event =
741 gesture_provider_.GetCurrentDownEvent();
742 if (!current_down_event)
743 return;
745 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
746 DCHECK(cancel_event);
747 OnTouchEvent(*cancel_event);
750 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
751 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
754 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
755 bool enabled) {
756 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
759 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
760 ime_adapter_android_.CancelComposition();
763 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
764 const gfx::Range& range,
765 const std::vector<gfx::Rect>& character_bounds) {
766 // TODO(yukawa): Implement this.
769 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
770 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
771 if (selection_controller_)
772 selection_controller_->OnSelectionEditable(is_editable_node);
775 void RenderWidgetHostViewAndroid::RenderProcessGone(
776 base::TerminationStatus status, int error_code) {
777 Destroy();
780 void RenderWidgetHostViewAndroid::Destroy() {
781 RemoveLayers();
782 SetContentViewCore(NULL);
784 // The RenderWidgetHost's destruction led here, so don't call it.
785 host_ = NULL;
787 delete this;
790 void RenderWidgetHostViewAndroid::SetTooltipText(
791 const base::string16& tooltip_text) {
792 // Tooltips don't makes sense on Android.
795 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
796 size_t offset,
797 const gfx::Range& range) {
798 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
800 if (selection_controller_)
801 selection_controller_->OnSelectionEmpty(text.empty());
803 if (!content_view_core_)
804 return;
805 if (range.is_empty()) {
806 content_view_core_->OnSelectionChanged("");
807 return;
810 DCHECK(!text.empty());
811 size_t pos = range.GetMin() - offset;
812 size_t n = range.length();
814 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
815 if (pos >= text.length()) {
816 NOTREACHED() << "The text can not cover range.";
817 return;
820 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
822 content_view_core_->OnSelectionChanged(utf8_selection);
825 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
826 const ViewHostMsg_SelectionBounds_Params& params) {
827 NOTREACHED() << "Selection bounds should be routed through the compositor.";
830 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
831 RenderWidgetHostViewBase::SetBackgroundColor(color);
832 host_->SetBackgroundOpaque(GetBackgroundOpaque());
833 OnDidChangeBodyBackgroundColor(color);
836 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
837 const gfx::Rect& src_subrect,
838 const gfx::Size& dst_size,
839 CopyFromCompositingSurfaceCallback& callback,
840 const SkColorType color_type) {
841 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
842 if ((!host_ || host_->is_hidden()) ||
843 !IsReadbackConfigSupported(color_type)) {
844 callback.Run(false, SkBitmap());
845 return;
847 base::TimeTicks start_time = base::TimeTicks::Now();
848 if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
849 callback.Run(false, SkBitmap());
850 return;
852 const gfx::Display& display =
853 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
854 float device_scale_factor = display.device_scale_factor();
855 gfx::Size dst_size_in_pixel =
856 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
857 gfx::Rect src_subrect_in_pixel =
858 ConvertRectToPixel(device_scale_factor, src_subrect);
860 if (using_synchronous_compositor_) {
861 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
862 color_type);
863 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
864 base::TimeTicks::Now() - start_time);
865 return;
868 scoped_ptr<cc::CopyOutputRequest> request;
869 scoped_refptr<cc::Layer> readback_layer;
870 DCHECK(content_view_core_);
871 DCHECK(content_view_core_->GetWindowAndroid());
872 ui::WindowAndroidCompositor* compositor =
873 content_view_core_->GetWindowAndroid()->GetCompositor();
874 DCHECK(compositor);
875 DCHECK(frame_provider_.get());
876 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
877 CreateDelegatedLayerForFrameProvider();
878 delegated_layer->SetHideLayerAndSubtree(true);
879 compositor->AttachLayerForReadback(delegated_layer);
881 readback_layer = delegated_layer;
882 request = cc::CopyOutputRequest::CreateRequest(
883 base::Bind(&RenderWidgetHostViewAndroid::
884 PrepareTextureCopyOutputResultForDelegatedReadback,
885 dst_size_in_pixel,
886 color_type,
887 start_time,
888 readback_layer,
889 callback));
890 request->set_area(src_subrect_in_pixel);
891 readback_layer->RequestCopyOfOutput(request.Pass());
894 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
895 const gfx::Rect& src_subrect,
896 const scoped_refptr<media::VideoFrame>& target,
897 const base::Callback<void(bool)>& callback) {
898 NOTIMPLEMENTED();
899 callback.Run(false);
902 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
903 return false;
906 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
907 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
908 if (!content_view_core_)
909 return;
911 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
914 scoped_ptr<SyntheticGestureTarget>
915 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
916 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
917 host_, content_view_core_->CreateTouchEventSynthesizer()));
920 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
921 uint32 output_surface_id) {
922 DCHECK(host_);
923 cc::CompositorFrameAck ack;
924 if (resource_collection_.get())
925 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
926 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
927 output_surface_id,
928 host_->GetProcess()->GetID(),
929 ack);
932 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
933 uint32 output_surface_id) {
934 DCHECK(resource_collection_.get());
936 cc::CompositorFrameAck ack;
937 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
938 DCHECK(!ack.resources.empty());
940 RenderWidgetHostImpl::SendReclaimCompositorResources(
941 host_->GetRoutingID(),
942 output_surface_id,
943 host_->GetProcess()->GetID(),
944 ack);
947 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
948 if (ack_callbacks_.size())
949 return;
950 SendReturnedDelegatedResources(last_output_surface_id_);
953 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
954 RemoveLayers();
955 frame_provider_ = NULL;
956 layer_ = NULL;
957 // This gets called when ever any eviction, loosing resources, swapping
958 // problems are encountered and so we abort any pending readbacks here.
959 AbortPendingReadbackRequests();
962 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
963 uint32 output_surface_id,
964 scoped_ptr<cc::DelegatedFrameData> frame_data) {
965 bool has_content = !texture_size_in_layer_.IsEmpty();
967 if (output_surface_id != last_output_surface_id_) {
968 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
969 // any resources from the old output surface with the new output surface id.
970 if (resource_collection_.get()) {
971 resource_collection_->SetClient(NULL);
972 if (resource_collection_->LoseAllResources())
973 SendReturnedDelegatedResources(last_output_surface_id_);
974 resource_collection_ = NULL;
976 DestroyDelegatedContent();
978 last_output_surface_id_ = output_surface_id;
981 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
982 // renderer frame, assuming that the browser compositor will scale
983 // it back up to device scale. But on Android we put our browser layers in
984 // physical pixels and set our browser CC device_scale_factor to 1, so this
985 // suppresses the transform. This line may need to be removed when fixing
986 // http://crbug.com/384134 or http://crbug.com/310763
987 frame_data->device_scale_factor = 1.0f;
989 if (!has_content) {
990 DestroyDelegatedContent();
991 } else {
992 if (!resource_collection_.get()) {
993 resource_collection_ = new cc::DelegatedFrameResourceCollection;
994 resource_collection_->SetClient(this);
996 if (!frame_provider_.get() ||
997 texture_size_in_layer_ != frame_provider_->frame_size()) {
998 RemoveLayers();
999 frame_provider_ = new cc::DelegatedFrameProvider(
1000 resource_collection_.get(), frame_data.Pass());
1001 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
1002 AttachLayers();
1003 } else {
1004 frame_provider_->SetFrameData(frame_data.Pass());
1008 if (layer_.get()) {
1009 layer_->SetIsDrawable(true);
1010 layer_->SetContentsOpaque(true);
1011 layer_->SetBounds(content_size_in_layer_);
1012 layer_->SetNeedsDisplay();
1015 base::Closure ack_callback =
1016 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1017 weak_ptr_factory_.GetWeakPtr(),
1018 output_surface_id);
1020 ack_callbacks_.push(ack_callback);
1021 if (host_->is_hidden())
1022 RunAckCallbacks();
1025 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1026 const cc::CompositorFrameMetadata& frame_metadata) {
1027 // Calculate the content size. This should be 0 if the texture_size is 0.
1028 gfx::Vector2dF offset;
1029 if (texture_size_in_layer_.IsEmpty())
1030 content_size_in_layer_ = gfx::Size();
1031 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1032 frame_metadata.scrollable_viewport_size,
1033 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1035 if (overscroll_effect_) {
1036 overscroll_effect_->UpdateDisplayParameters(
1037 CreateOverscrollDisplayParameters(frame_metadata));
1041 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1042 uint32 output_surface_id,
1043 scoped_ptr<cc::CompositorFrame> frame) {
1044 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1045 if (!frame->delegated_frame_data) {
1046 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1047 return;
1050 if (locks_on_frame_count_ > 0) {
1051 DCHECK(HasValidFrame());
1052 RetainFrame(output_surface_id, frame.Pass());
1053 return;
1056 if (layer_.get() && layer_->layer_tree_host()) {
1057 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1058 scoped_ptr<cc::SwapPromise> swap_promise(
1059 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1060 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1064 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1066 cc::RenderPass* root_pass =
1067 frame->delegated_frame_data->render_pass_list.back();
1068 texture_size_in_layer_ = root_pass->output_rect.size();
1069 ComputeContentsSize(frame->metadata);
1071 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1072 frame_evictor_->SwappedFrame(!host_->is_hidden());
1074 // As the metadata update may trigger view invalidation, always call it after
1075 // any potential compositor scheduling.
1076 OnFrameMetadataUpdated(frame->metadata);
1077 // Check if we have any pending readbacks, see if we have a frame available
1078 // and process them here.
1079 if (!readbacks_waiting_for_frame_.empty()) {
1080 while (!readbacks_waiting_for_frame_.empty()) {
1081 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
1082 GetScaledContentBitmap(readback_request.GetScale(),
1083 readback_request.GetColorFormat(),
1084 readback_request.GetCaptureRect(),
1085 readback_request.GetResultCallback());
1086 readbacks_waiting_for_frame_.pop();
1091 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1092 uint32 output_surface_id,
1093 scoped_ptr<cc::CompositorFrame> frame) {
1094 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1097 void RenderWidgetHostViewAndroid::RetainFrame(
1098 uint32 output_surface_id,
1099 scoped_ptr<cc::CompositorFrame> frame) {
1100 DCHECK(locks_on_frame_count_);
1102 // Store the incoming frame so that it can be swapped when all the locks have
1103 // been released. If there is already a stored frame, then replace and skip
1104 // the previous one but make sure we still eventually send the ACK. Holding
1105 // the ACK also blocks the renderer when its max_frames_pending is reached.
1106 if (last_frame_info_) {
1107 base::Closure ack_callback =
1108 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1109 weak_ptr_factory_.GetWeakPtr(),
1110 last_frame_info_->output_surface_id);
1112 ack_callbacks_.push(ack_callback);
1115 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1118 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1119 const cc::CompositorFrameMetadata& frame_metadata) {
1120 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1121 // compositor flow.
1122 OnFrameMetadataUpdated(frame_metadata);
1123 ComputeContentsSize(frame_metadata);
1125 // DevTools ScreenCast support for Android WebView.
1126 WebContents* web_contents = content_view_core_->GetWebContents();
1127 if (DevToolsAgentHost::HasFor(web_contents)) {
1128 scoped_refptr<DevToolsAgentHost> dtah =
1129 DevToolsAgentHost::GetOrCreateFor(web_contents);
1130 // Unblock the compositor.
1131 BrowserThread::PostTask(
1132 BrowserThread::UI, FROM_HERE,
1133 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
1134 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
1135 frame_metadata));
1139 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1140 if (layer_.get())
1141 layer_->SetContentsOpaque(!enabled);
1144 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1145 // The synchronous (WebView) compositor does not have a proper browser
1146 // compositor with which to drive animations.
1147 return !using_synchronous_compositor_;
1150 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1151 DCHECK(content_view_core_);
1152 DCHECK(!using_synchronous_compositor_);
1153 content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1156 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1157 MoveCaret(gfx::Point(position.x(), position.y()));
1160 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1161 const gfx::PointF& start,
1162 const gfx::PointF& end) {
1163 DCHECK(content_view_core_);
1164 content_view_core_->SelectBetweenCoordinates(start, end);
1167 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1168 SelectionEventType event,
1169 const gfx::PointF& position) {
1170 DCHECK(content_view_core_);
1171 content_view_core_->OnSelectionEvent(event, position);
1174 scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
1175 DCHECK(content_view_core_);
1176 if (using_synchronous_compositor_)
1177 return content_view_core_->CreatePopupTouchHandleDrawable();
1179 return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1180 content_view_core_->GetLayer().get(),
1181 content_view_core_->GetDpiScale(),
1182 base::android::GetApplicationContext()));
1185 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1186 const gfx::Rect& src_subrect_in_pixel,
1187 const gfx::Size& dst_size_in_pixel,
1188 const base::Callback<void(bool, const SkBitmap&)>& callback,
1189 const SkColorType color_type) {
1190 SynchronousCompositor* compositor =
1191 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1192 host_->GetRoutingID());
1193 if (!compositor) {
1194 callback.Run(false, SkBitmap());
1195 return;
1198 SkBitmap bitmap;
1199 bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1200 dst_size_in_pixel.height(),
1201 color_type,
1202 kPremul_SkAlphaType));
1203 SkCanvas canvas(bitmap);
1204 canvas.scale(
1205 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
1206 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
1207 compositor->DemandDrawSw(&canvas);
1208 callback.Run(true, bitmap);
1211 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1212 const cc::CompositorFrameMetadata& frame_metadata) {
1214 // Disable double tap zoom for pages that have a width=device-width or
1215 // narrower viewport (indicating that this is a mobile-optimized or responsive
1216 // web design, so text will be legible without zooming). Also disable
1217 // double tap and pinch for pages that prevent zooming in or out.
1218 bool has_mobile_viewport = HasMobileViewport(frame_metadata);
1219 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
1220 gesture_provider_.SetDoubleTapSupportForPageEnabled(
1221 !has_fixed_page_scale && !has_mobile_viewport);
1223 if (!content_view_core_)
1224 return;
1226 if (selection_controller_) {
1227 selection_controller_->OnSelectionBoundsChanged(
1228 frame_metadata.selection_start, frame_metadata.selection_end);
1231 // All offsets and sizes are in CSS pixels.
1232 content_view_core_->UpdateFrameInfo(
1233 frame_metadata.root_scroll_offset,
1234 frame_metadata.page_scale_factor,
1235 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1236 frame_metadata.max_page_scale_factor),
1237 frame_metadata.root_layer_size,
1238 frame_metadata.scrollable_viewport_size,
1239 frame_metadata.location_bar_offset,
1240 frame_metadata.location_bar_content_translation);
1241 #if defined(VIDEO_HOLE)
1242 if (host_ && host_->IsRenderView()) {
1243 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1244 RenderViewHost::From(host_));
1245 rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
1247 #endif // defined(VIDEO_HOLE)
1250 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
1251 // TODO: remove need for the surface id here
1252 accelerated_surface_route_id_ = route_id;
1255 void RenderWidgetHostViewAndroid::AttachLayers() {
1256 if (!content_view_core_)
1257 return;
1258 if (!layer_.get())
1259 return;
1261 content_view_core_->AttachLayer(layer_);
1262 if (overscroll_effect_)
1263 overscroll_effect_->Enable();
1264 layer_->SetHideLayerAndSubtree(!is_showing_);
1267 void RenderWidgetHostViewAndroid::RemoveLayers() {
1268 if (!content_view_core_)
1269 return;
1271 if (!layer_.get())
1272 return;
1274 content_view_core_->RemoveLayer(layer_);
1275 if (overscroll_effect_)
1276 overscroll_effect_->Disable();
1279 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1280 // The synchronous compositor does not requre BeginFrame messages.
1281 if (using_synchronous_compositor_)
1282 requests &= FLUSH_INPUT;
1284 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1285 outstanding_vsync_requests_ |= requests;
1286 // Note that if we're not currently observing the root window, outstanding
1287 // vsync requests will be pushed if/when we resume observing in
1288 // |StartObservingRootWindow()|.
1289 if (observing_root_window_ && should_request_vsync)
1290 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1293 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1294 DCHECK(content_view_core_);
1295 if (observing_root_window_)
1296 return;
1298 observing_root_window_ = true;
1299 content_view_core_->GetWindowAndroid()->AddObserver(this);
1301 // Clear existing vsync requests to allow a request to the new window.
1302 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1303 outstanding_vsync_requests_ = 0;
1304 RequestVSyncUpdate(outstanding_vsync_requests);
1307 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1308 if (!content_view_core_) {
1309 DCHECK(!observing_root_window_);
1310 return;
1313 if (!observing_root_window_)
1314 return;
1316 observing_root_window_ = false;
1317 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1320 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1321 base::TimeDelta vsync_period) {
1322 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1323 "frame_time_us", frame_time.ToInternalValue());
1324 base::TimeTicks display_time = frame_time + vsync_period;
1326 base::TimeTicks deadline =
1327 display_time - host_->GetEstimatedBrowserCompositeTime();
1329 host_->Send(new ViewMsg_BeginFrame(
1330 host_->GetRoutingID(),
1331 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
1334 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1335 bool needs_animate =
1336 overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
1337 if (selection_controller_)
1338 needs_animate |= selection_controller_->Animate(frame_time);
1339 return needs_animate;
1342 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1343 if (layer_.get())
1344 DestroyDelegatedContent();
1345 frame_evictor_->DiscardedFrame();
1346 // We are evicting the delegated frame,
1347 // so there should be no pending readback requests
1348 DCHECK(readbacks_waiting_for_frame_.empty());
1351 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1352 const gfx::Size& desired_size) {
1353 NOTREACHED();
1354 return false;
1357 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1358 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1359 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1362 // TODO(jrg): Find out the implications and answer correctly here,
1363 // as we are returning the WebView and not root window bounds.
1364 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1365 return GetViewBounds();
1368 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1369 gfx::GLSurfaceHandle handle =
1370 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
1371 if (CompositorImpl::IsInitialized()) {
1372 handle.parent_client_id =
1373 ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
1375 return handle;
1378 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1379 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1380 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1381 gesture_provider_.OnTouchEventAck(event_consumed);
1384 void RenderWidgetHostViewAndroid::GestureEventAck(
1385 const blink::WebGestureEvent& event,
1386 InputEventAckState ack_result) {
1387 // The overscroll effect requires an explicit release signal that may not be
1388 // sent from the renderer compositor.
1389 if (event.type == blink::WebInputEvent::GestureScrollEnd ||
1390 event.type == blink::WebInputEvent::GestureFlingStart) {
1391 DidOverscroll(DidOverscrollParams());
1394 if (content_view_core_)
1395 content_view_core_->OnGestureEventAck(event, ack_result);
1398 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1399 const blink::WebInputEvent& input_event) {
1400 if (selection_controller_) {
1401 switch (input_event.type) {
1402 case blink::WebInputEvent::GestureLongPress:
1403 selection_controller_->OnLongPressEvent();
1404 break;
1405 case blink::WebInputEvent::GestureTap:
1406 selection_controller_->OnTapEvent();
1407 break;
1408 default:
1409 break;
1413 if (content_view_core_ &&
1414 content_view_core_->FilterInputEvent(input_event))
1415 return INPUT_EVENT_ACK_STATE_CONSUMED;
1417 if (!host_)
1418 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1420 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1421 input_event.type == blink::WebInputEvent::TouchStart) {
1422 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1423 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1424 if (shim && gpu_data && accelerated_surface_route_id_ &&
1425 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1426 shim->Send(
1427 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1430 SynchronousCompositorImpl* compositor =
1431 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1432 host_->GetRoutingID());
1433 if (compositor)
1434 return compositor->HandleInputEvent(input_event);
1435 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1438 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1439 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1440 RequestVSyncUpdate(FLUSH_INPUT);
1443 BrowserAccessibilityManager*
1444 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1445 BrowserAccessibilityDelegate* delegate) {
1446 // TODO(dmazzoni): Currently there can only be one
1447 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1448 // if there's already a BrowserAccessibilityManager for the main
1449 // frame. Eventually, in order to support cross-process iframes on
1450 // Android we'll need to add support for a
1451 // BrowserAccessibilityManager for a child frame.
1452 // http://crbug.com/423846
1453 if (!host_ || host_->GetRootBrowserAccessibilityManager())
1454 return NULL;
1456 base::android::ScopedJavaLocalRef<jobject> obj;
1457 if (content_view_core_)
1458 obj = content_view_core_->GetJavaObject();
1459 return new BrowserAccessibilityManagerAndroid(
1460 obj,
1461 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1462 delegate);
1465 bool RenderWidgetHostViewAndroid::LockMouse() {
1466 NOTIMPLEMENTED();
1467 return false;
1470 void RenderWidgetHostViewAndroid::UnlockMouse() {
1471 NOTIMPLEMENTED();
1474 // Methods called from the host to the render
1476 void RenderWidgetHostViewAndroid::SendKeyEvent(
1477 const NativeWebKeyboardEvent& event) {
1478 if (host_)
1479 host_->ForwardKeyboardEvent(event);
1482 void RenderWidgetHostViewAndroid::SendMouseEvent(
1483 const blink::WebMouseEvent& event) {
1484 if (host_)
1485 host_->ForwardMouseEvent(event);
1488 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1489 const blink::WebMouseWheelEvent& event) {
1490 if (host_)
1491 host_->ForwardWheelEvent(event);
1494 void RenderWidgetHostViewAndroid::SendGestureEvent(
1495 const blink::WebGestureEvent& event) {
1496 // Sending a gesture that may trigger overscroll should resume the effect.
1497 if (overscroll_effect_)
1498 overscroll_effect_->Enable();
1500 if (host_)
1501 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1504 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1505 if (host_)
1506 host_->MoveCaret(point);
1509 void RenderWidgetHostViewAndroid::HideTextHandles() {
1510 if (selection_controller_)
1511 selection_controller_->HideAndDisallowShowingAutomatically();
1514 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1515 const gfx::PointF& point) {
1516 if (!selection_controller_)
1517 return;
1519 // As the paste popup may be triggered *before* the bounds and editability
1520 // of the region have been updated, explicitly set the properties now.
1521 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1522 // notifications are no longer required, crbug.com/398170.
1523 cc::ViewportSelectionBound insertion_bound;
1524 insertion_bound.type = cc::SELECTION_BOUND_CENTER;
1525 insertion_bound.visible = true;
1526 insertion_bound.edge_top = point;
1527 insertion_bound.edge_bottom = point;
1528 HideTextHandles();
1529 ShowSelectionHandlesAutomatically();
1530 selection_controller_->OnSelectionEditable(true);
1531 selection_controller_->OnSelectionEmpty(true);
1532 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1533 insertion_bound);
1536 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1537 return cached_background_color_;
1540 void RenderWidgetHostViewAndroid::DidOverscroll(
1541 const DidOverscrollParams& params) {
1542 if (!content_view_core_ || !layer_.get() || !is_showing_)
1543 return;
1545 const float device_scale_factor = content_view_core_->GetDpiScale();
1547 if (overscroll_effect_ &&
1548 overscroll_effect_->OnOverscrolled(
1549 content_view_core_->GetLayer().get(),
1550 base::TimeTicks::Now(),
1551 gfx::ScaleVector2d(params.accumulated_overscroll,
1552 device_scale_factor),
1553 gfx::ScaleVector2d(params.latest_overscroll_delta,
1554 device_scale_factor),
1555 gfx::ScaleVector2d(params.current_fling_velocity,
1556 device_scale_factor),
1557 gfx::ScaleVector2d(
1558 params.causal_event_viewport_point.OffsetFromOrigin(),
1559 device_scale_factor))) {
1560 SetNeedsAnimate();
1564 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1565 if (content_view_core_)
1566 content_view_core_->DidStopFlinging();
1569 void RenderWidgetHostViewAndroid::SetContentViewCore(
1570 ContentViewCoreImpl* content_view_core) {
1571 RemoveLayers();
1572 StopObservingRootWindow();
1574 bool resize = false;
1575 if (content_view_core != content_view_core_) {
1576 overscroll_effect_.reset();
1577 selection_controller_.reset();
1578 ReleaseLocksOnSurface();
1579 resize = true;
1582 content_view_core_ = content_view_core;
1584 BrowserAccessibilityManager* manager = NULL;
1585 if (host_)
1586 manager = host_->GetRootBrowserAccessibilityManager();
1587 if (manager) {
1588 base::android::ScopedJavaLocalRef<jobject> obj;
1589 if (content_view_core_)
1590 obj = content_view_core_->GetJavaObject();
1591 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1594 AttachLayers();
1596 if (!content_view_core_)
1597 return;
1599 StartObservingRootWindow();
1601 if (resize)
1602 WasResized();
1604 if (!selection_controller_)
1605 selection_controller_ = CreateSelectionController(this, content_view_core_);
1607 if (overscroll_effect_enabled_ && !overscroll_effect_ &&
1608 content_view_core_->GetWindowAndroid()->GetCompositor())
1609 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1612 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1613 while (!ack_callbacks_.empty()) {
1614 ack_callbacks_.front().Run();
1615 ack_callbacks_.pop();
1619 void RenderWidgetHostViewAndroid::OnGestureEvent(
1620 const ui::GestureEventData& gesture) {
1621 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
1624 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1625 RunAckCallbacks();
1628 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1629 DCHECK(content_view_core_);
1630 if (overscroll_effect_enabled_ && !overscroll_effect_)
1631 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1634 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1635 DCHECK(content_view_core_);
1636 DCHECK(!using_synchronous_compositor_);
1637 RunAckCallbacks();
1638 overscroll_effect_.reset();
1641 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1642 base::TimeDelta vsync_period) {
1643 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1644 if (!host_)
1645 return;
1647 const uint32 current_vsync_requests = outstanding_vsync_requests_;
1648 outstanding_vsync_requests_ = 0;
1650 if (current_vsync_requests & FLUSH_INPUT)
1651 host_->FlushInput();
1653 if (current_vsync_requests & BEGIN_FRAME ||
1654 current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
1655 SendBeginFrame(frame_time, vsync_period);
1658 if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
1659 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
1662 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1663 if (Animate(begin_frame_time))
1664 SetNeedsAnimate();
1667 void RenderWidgetHostViewAndroid::OnLostResources() {
1668 ReleaseLocksOnSurface();
1669 if (layer_.get())
1670 DestroyDelegatedContent();
1671 DCHECK(ack_callbacks_.empty());
1672 // We should not loose a frame if we have readback requests pending.
1673 DCHECK(readbacks_waiting_for_frame_.empty());
1676 // static
1677 void
1678 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1679 const gfx::Size& dst_size_in_pixel,
1680 const SkColorType color_type,
1681 const base::TimeTicks& start_time,
1682 scoped_refptr<cc::Layer> readback_layer,
1683 const base::Callback<void(bool, const SkBitmap&)>& callback,
1684 scoped_ptr<cc::CopyOutputResult> result) {
1685 readback_layer->RemoveFromParent();
1686 PrepareTextureCopyOutputResult(
1687 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1690 // static
1691 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1692 const gfx::Size& dst_size_in_pixel,
1693 const SkColorType color_type,
1694 const base::TimeTicks& start_time,
1695 const base::Callback<void(bool, const SkBitmap&)>& callback,
1696 scoped_ptr<cc::CopyOutputResult> result) {
1697 base::ScopedClosureRunner scoped_callback_runner(
1698 base::Bind(callback, false, SkBitmap()));
1699 TRACE_EVENT0("cc",
1700 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1702 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1703 return;
1705 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1706 if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1707 dst_size_in_pixel.height(),
1708 color_type,
1709 kOpaque_SkAlphaType)))
1710 return;
1712 ImageTransportFactoryAndroid* factory =
1713 ImageTransportFactoryAndroid::GetInstance();
1714 GLHelper* gl_helper = factory->GetGLHelper();
1716 if (!gl_helper)
1717 return;
1719 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1720 new SkAutoLockPixels(*bitmap));
1721 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1723 cc::TextureMailbox texture_mailbox;
1724 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1725 result->TakeTexture(&texture_mailbox, &release_callback);
1726 DCHECK(texture_mailbox.IsTexture());
1727 if (!texture_mailbox.IsTexture())
1728 return;
1730 ignore_result(scoped_callback_runner.Release());
1732 gl_helper->CropScaleReadbackAndCleanMailbox(
1733 texture_mailbox.mailbox(),
1734 texture_mailbox.sync_point(),
1735 result->size(),
1736 gfx::Rect(result->size()),
1737 dst_size_in_pixel,
1738 pixels,
1739 color_type,
1740 base::Bind(&CopyFromCompositingSurfaceFinished,
1741 callback,
1742 base::Passed(&release_callback),
1743 base::Passed(&bitmap),
1744 start_time,
1745 base::Passed(&bitmap_pixels_lock)),
1746 GLHelper::SCALER_QUALITY_GOOD);
1749 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1750 SkColorType color_type) {
1751 ImageTransportFactoryAndroid* factory =
1752 ImageTransportFactoryAndroid::GetInstance();
1753 GLHelper* gl_helper = factory->GetGLHelper();
1754 if (!gl_helper)
1755 return false;
1756 return gl_helper->IsReadbackConfigSupported(color_type);
1759 SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1760 // Define the criteria here. If say the 16 texture readback is
1761 // supported we should go with that (this degrades quality)
1762 // or stick back to the default format.
1763 if (base::SysInfo::IsLowEndDevice()) {
1764 if (IsReadbackConfigSupported(kRGB_565_SkColorType))
1765 return kRGB_565_SkColorType;
1767 return kN32_SkColorType;
1770 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1771 // Fake a long press to allow automatic selection handle showing.
1772 if (selection_controller_)
1773 selection_controller_->OnLongPressEvent();
1776 void RenderWidgetHostViewAndroid::SelectRange(
1777 float x1, float y1, float x2, float y2) {
1778 if (content_view_core_)
1779 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
1780 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
1783 void RenderWidgetHostViewAndroid::LongPress(
1784 base::TimeTicks time, float x, float y) {
1785 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
1786 blink::WebInputEvent::GestureLongPress,
1787 (time - base::TimeTicks()).InSecondsF(), x, y);
1788 SendGestureEvent(long_press);
1791 // static
1792 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1793 blink::WebScreenInfo* results) {
1794 const gfx::Display& display =
1795 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1796 results->rect = display.bounds();
1797 // TODO(husky): Remove any system controls from availableRect.
1798 results->availableRect = display.work_area();
1799 results->deviceScaleFactor = display.device_scale_factor();
1800 results->orientationAngle = display.RotationAsDegree();
1801 results->orientationType =
1802 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
1803 gfx::DeviceDisplayInfo info;
1804 results->depth = info.GetBitsPerPixel();
1805 results->depthPerComponent = info.GetBitsPerComponent();
1806 results->isMonochrome = (results->depthPerComponent == 0);
1809 } // namespace content