Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blobeaa2c5a255ab45b9cd8858db1a2d574d9397f426
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_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/display.h"
76 #include "ui/gfx/screen.h"
77 #include "ui/gfx/size_conversions.h"
79 namespace content {
81 namespace {
83 const int kUndefinedOutputSurfaceId = -1;
85 // Used to accomodate finite precision when comparing scaled viewport and
86 // content widths. While this value may seem large, width=device-width on an N7
87 // V1 saw errors of ~0.065 between computed window and content widths.
88 const float kMobileViewportWidthEpsilon = 0.15f;
90 // Used for conditional creation of EdgeEffect types for overscroll.
91 const int kKitKatMR2SDKVersion = 19;
93 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
95 // Sends an acknowledgement to the renderer of a processed IME event.
96 void SendImeEventAck(RenderWidgetHostImpl* host) {
97 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
100 void CopyFromCompositingSurfaceFinished(
101 const base::Callback<void(bool, const SkBitmap&)>& callback,
102 scoped_ptr<cc::SingleReleaseCallback> release_callback,
103 scoped_ptr<SkBitmap> bitmap,
104 const base::TimeTicks& start_time,
105 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
106 bool result) {
107 TRACE_EVENT0(
108 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
109 bitmap_pixels_lock.reset();
110 release_callback->Run(0, false);
111 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
112 base::TimeTicks::Now() - start_time);
113 callback.Run(result, *bitmap);
116 ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
117 ui::LatencyInfo latency_info;
118 // The latency number should only be added if the timestamp is valid.
119 if (event.timeStampSeconds) {
120 const int64 time_micros = static_cast<int64>(
121 event.timeStampSeconds * base::Time::kMicrosecondsPerSecond);
122 latency_info.AddLatencyNumberWithTimestamp(
123 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
126 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
129 return latency_info;
132 OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
133 const cc::CompositorFrameMetadata& frame_metadata) {
134 const float scale_factor =
135 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
137 // Compute the size and offsets for each edge, where each effect is sized to
138 // the viewport and offset by the distance of each viewport edge to the
139 // respective content edge.
140 OverscrollGlow::DisplayParameters params;
141 params.size = gfx::ScaleSize(
142 frame_metadata.scrollable_viewport_size, scale_factor);
143 params.edge_offsets[OverscrollGlow::EDGE_TOP] =
144 -frame_metadata.root_scroll_offset.y() * scale_factor;
145 params.edge_offsets[OverscrollGlow::EDGE_LEFT] =
146 -frame_metadata.root_scroll_offset.x() * scale_factor;
147 params.edge_offsets[OverscrollGlow::EDGE_BOTTOM] =
148 (frame_metadata.root_layer_size.height() -
149 frame_metadata.root_scroll_offset.y() -
150 frame_metadata.scrollable_viewport_size.height()) *
151 scale_factor;
152 params.edge_offsets[OverscrollGlow::EDGE_RIGHT] =
153 (frame_metadata.root_layer_size.width() -
154 frame_metadata.root_scroll_offset.x() -
155 frame_metadata.scrollable_viewport_size.width()) *
156 scale_factor;
158 return params;
161 bool UseEdgeEffectL() {
162 static bool use_edge_effect_l =
163 base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
164 return use_edge_effect_l;
167 scoped_ptr<EdgeEffectBase> CreateEdgeEffect(
168 ui::SystemUIResourceManager* resource_manager,
169 float device_scale_factor) {
170 DCHECK(resource_manager);
171 if (UseEdgeEffectL())
172 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
174 return scoped_ptr<EdgeEffectBase>(
175 new EdgeEffect(resource_manager, device_scale_factor));
178 scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
179 ContentViewCore* content_view_core) {
180 DCHECK(content_view_core);
181 ui::WindowAndroidCompositor* compositor =
182 content_view_core->GetWindowAndroid()->GetCompositor();
183 DCHECK(compositor);
184 ui::SystemUIResourceManager* system_resource_manager =
185 &compositor->GetSystemUIResourceManager();
187 if (UseEdgeEffectL())
188 EdgeEffectL::PreloadResources(system_resource_manager);
189 else
190 EdgeEffect::PreloadResources(system_resource_manager);
192 return make_scoped_ptr(
193 new OverscrollGlow(base::Bind(&CreateEdgeEffect,
194 system_resource_manager,
195 content_view_core->GetDpiScale())));
198 ui::GestureProvider::Config CreateGestureProviderConfig() {
199 ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
200 config.disable_click_delay =
201 base::CommandLine::ForCurrentProcess()->HasSwitch(
202 switches::kDisableClickDelay);
203 return config;
206 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
207 return frame_metadata.min_page_scale_factor ==
208 frame_metadata.max_page_scale_factor;
211 bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
212 float window_width_dip =
213 frame_metadata.page_scale_factor *
214 frame_metadata.scrollable_viewport_size.width();
215 float content_width_css = frame_metadata.root_layer_size.width();
216 return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
219 } // anonymous namespace
221 ReadbackRequest::ReadbackRequest(
222 float scale,
223 SkColorType color_type,
224 gfx::Rect src_subrect,
225 const base::Callback<void(bool, const SkBitmap&)>& result_callback)
226 : scale_(scale),
227 color_type_(color_type),
228 src_subrect_(src_subrect),
229 result_callback_(result_callback) {
232 ReadbackRequest::ReadbackRequest() {
235 ReadbackRequest::~ReadbackRequest() {
238 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
239 uint32 output_id,
240 scoped_ptr<cc::CompositorFrame> output_frame)
241 : output_surface_id(output_id), frame(output_frame.Pass()) {}
243 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
245 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
246 RenderWidgetHostImpl* widget_host,
247 ContentViewCoreImpl* content_view_core)
248 : host_(widget_host),
249 outstanding_vsync_requests_(0),
250 is_showing_(!widget_host->is_hidden()),
251 content_view_core_(NULL),
252 ime_adapter_android_(this),
253 cached_background_color_(SK_ColorWHITE),
254 last_output_surface_id_(kUndefinedOutputSurfaceId),
255 weak_ptr_factory_(this),
256 overscroll_effect_enabled_(
257 !base::CommandLine::ForCurrentProcess()->HasSwitch(
258 switches::kDisableOverscrollEdgeEffect)),
259 gesture_provider_(CreateGestureProviderConfig(), this),
260 gesture_text_selector_(this),
261 touch_scrolling_(false),
262 potentially_active_fling_count_(0),
263 accelerated_surface_route_id_(0),
264 using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
265 widget_host->GetProcess()->GetID(),
266 widget_host->GetRoutingID()) != NULL),
267 frame_evictor_(new DelegatedFrameEvictor(this)),
268 locks_on_frame_count_(0),
269 observing_root_window_(false) {
270 host_->SetView(this);
271 SetContentViewCore(content_view_core);
272 ImageTransportFactoryAndroid::AddObserver(this);
275 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
276 ImageTransportFactoryAndroid::RemoveObserver(this);
277 SetContentViewCore(NULL);
278 DCHECK(ack_callbacks_.empty());
279 DCHECK(readbacks_waiting_for_frame_.empty());
280 if (resource_collection_.get())
281 resource_collection_->SetClient(NULL);
285 bool RenderWidgetHostViewAndroid::OnMessageReceived(
286 const IPC::Message& message) {
287 bool handled = true;
288 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
289 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
290 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
291 OnDidChangeBodyBackgroundColor)
292 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
293 OnSetNeedsBeginFrame)
294 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
295 OnSmartClipDataExtracted)
296 IPC_MESSAGE_UNHANDLED(handled = false)
297 IPC_END_MESSAGE_MAP()
298 return handled;
301 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
302 NOTIMPLEMENTED();
305 void RenderWidgetHostViewAndroid::InitAsPopup(
306 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
307 NOTIMPLEMENTED();
310 void RenderWidgetHostViewAndroid::InitAsFullscreen(
311 RenderWidgetHostView* reference_host_view) {
312 NOTIMPLEMENTED();
315 RenderWidgetHost*
316 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
317 return host_;
320 void RenderWidgetHostViewAndroid::WasShown() {
321 if (!host_ || !host_->is_hidden())
322 return;
324 host_->WasShown(ui::LatencyInfo());
326 if (content_view_core_) {
327 StartObservingRootWindow();
328 RequestVSyncUpdate(BEGIN_FRAME);
332 void RenderWidgetHostViewAndroid::WasHidden() {
333 RunAckCallbacks();
335 if (!host_ || host_->is_hidden())
336 return;
338 // Inform the renderer that we are being hidden so it can reduce its resource
339 // utilization.
340 host_->WasHidden();
342 StopObservingRootWindow();
345 void RenderWidgetHostViewAndroid::WasResized() {
346 host_->WasResized();
349 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
350 // Ignore the given size as only the Java code has the power to
351 // resize the view on Android.
352 default_size_ = size;
355 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
356 SetSize(rect.size());
359 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
360 while (!readbacks_waiting_for_frame_.empty()) {
361 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
362 readback_request.GetResultCallback().Run(false, SkBitmap());
363 readbacks_waiting_for_frame_.pop();
367 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
368 float scale,
369 SkColorType color_type,
370 gfx::Rect src_subrect,
371 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
372 if (!host_ || host_->is_hidden()) {
373 result_callback.Run(false, SkBitmap());
374 return;
376 if (!IsSurfaceAvailableForCopy()) {
377 // The view is visible, probably the frame has not yet arrived.
378 // Just add the ReadbackRequest to queue and wait for frame arrival
379 // to get this request processed.
380 readbacks_waiting_for_frame_.push(
381 ReadbackRequest(scale, color_type, src_subrect, result_callback));
382 return;
385 gfx::Size bounds = layer_->bounds();
386 if (src_subrect.IsEmpty())
387 src_subrect = gfx::Rect(bounds);
388 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
389 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
390 const gfx::Display& display =
391 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
392 float device_scale_factor = display.device_scale_factor();
393 DCHECK_GT(device_scale_factor, 0);
394 gfx::Size dst_size(
395 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
396 CopyFromCompositingSurface(
397 src_subrect, dst_size, result_callback, color_type);
400 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
401 if (!content_view_core_)
402 return false;
403 if (!layer_)
404 return false;
406 if (texture_size_in_layer_.IsEmpty())
407 return false;
408 // This tell us whether a valid frame has arrived or not.
409 if (!frame_evictor_->HasFrame())
410 return false;
412 return true;
415 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
416 return content_view_core_->GetViewAndroid();
419 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
420 return reinterpret_cast<gfx::NativeViewId>(
421 const_cast<RenderWidgetHostViewAndroid*>(this));
424 gfx::NativeViewAccessible
425 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
426 NOTIMPLEMENTED();
427 return NULL;
430 void RenderWidgetHostViewAndroid::MovePluginWindows(
431 const std::vector<WebPluginGeometry>& moves) {
432 // We don't have plugin windows on Android. Do nothing. Note: this is called
433 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
434 // processing the corresponding message from Renderer.
437 void RenderWidgetHostViewAndroid::Focus() {
438 host_->Focus();
439 host_->SetInputMethodActive(true);
440 if (overscroll_effect_)
441 overscroll_effect_->Enable();
444 void RenderWidgetHostViewAndroid::Blur() {
445 host_->ExecuteEditCommand("Unselect", "");
446 host_->SetInputMethodActive(false);
447 host_->Blur();
448 if (overscroll_effect_)
449 overscroll_effect_->Disable();
452 bool RenderWidgetHostViewAndroid::HasFocus() const {
453 if (!content_view_core_)
454 return false; // ContentViewCore not created yet.
456 return content_view_core_->HasFocus();
459 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
460 return HasValidFrame();
463 void RenderWidgetHostViewAndroid::Show() {
464 if (is_showing_)
465 return;
467 is_showing_ = true;
468 if (layer_)
469 layer_->SetHideLayerAndSubtree(false);
471 frame_evictor_->SetVisible(true);
472 WasShown();
475 void RenderWidgetHostViewAndroid::Hide() {
476 if (!is_showing_)
477 return;
479 is_showing_ = false;
480 if (layer_ && locks_on_frame_count_ == 0)
481 layer_->SetHideLayerAndSubtree(true);
483 frame_evictor_->SetVisible(false);
484 // We don't know if we will ever get a frame if we are hiding the renderer, so
485 // we need to cancel all requests
486 AbortPendingReadbackRequests();
487 WasHidden();
490 bool RenderWidgetHostViewAndroid::IsShowing() {
491 // ContentViewCoreImpl represents the native side of the Java
492 // ContentViewCore. It being NULL means that it is not attached
493 // to the View system yet, so we treat this RWHVA as hidden.
494 return is_showing_ && content_view_core_;
497 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
498 DCHECK(HasValidFrame());
499 DCHECK(host_);
500 DCHECK(frame_evictor_->HasFrame());
501 frame_evictor_->LockFrame();
502 locks_on_frame_count_++;
505 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
506 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
507 return;
509 DCHECK(HasValidFrame());
510 frame_evictor_->UnlockFrame();
511 locks_on_frame_count_--;
513 if (locks_on_frame_count_ == 0) {
514 if (last_frame_info_) {
515 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
516 last_frame_info_->frame.Pass());
517 last_frame_info_.reset();
520 if (!is_showing_ && layer_)
521 layer_->SetHideLayerAndSubtree(true);
525 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
526 const TextSurroundingSelectionCallback& callback) {
527 // Only one outstanding request is allowed at any given time.
528 DCHECK(!callback.is_null());
529 text_surrounding_selection_callback_ = callback;
532 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
533 const base::string16& content,
534 size_t start_offset,
535 size_t end_offset) {
536 if (text_surrounding_selection_callback_.is_null())
537 return;
538 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
539 text_surrounding_selection_callback_.Reset();
542 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
543 if (!frame_evictor_->HasFrame()) {
544 DCHECK_EQ(locks_on_frame_count_, 0u);
545 return;
547 while (locks_on_frame_count_ > 0) {
548 UnlockCompositingSurface();
550 RunAckCallbacks();
553 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
554 if (!content_view_core_)
555 return gfx::Rect(default_size_);
557 return gfx::Rect(content_view_core_->GetViewSize());
560 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
561 if (!content_view_core_)
562 return gfx::Size();
564 return content_view_core_->GetPhysicalBackingSize();
567 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
568 if (!content_view_core_)
569 return 0.f;
571 // The amount that the viewport size given to Blink is shrunk by the URL-bar.
572 return content_view_core_->GetTopControlsLayoutHeightDip();
575 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
576 // There are no cursors on Android.
579 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
580 // Do nothing. The UI notification is handled through ContentViewClient which
581 // is TabContentsDelegate.
584 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
585 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
588 void RenderWidgetHostViewAndroid::TextInputStateChanged(
589 const ViewHostMsg_TextInputState_Params& params) {
590 if (selection_controller_) {
591 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
592 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
593 // while this call is present to ensure consistency with IME after
594 // navigation and tab focus changes
595 const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
596 selection_controller_->OnSelectionEditable(is_editable_node);
599 // If the change is not originated from IME (e.g. Javascript, autofill),
600 // send back the renderer an acknowledgement, regardless of how we exit from
601 // this method.
602 base::ScopedClosureRunner ack_caller;
603 if (params.is_non_ime_change)
604 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
606 if (!IsShowing())
607 return;
609 content_view_core_->UpdateImeAdapter(
610 GetNativeImeAdapter(),
611 static_cast<int>(params.type), params.flags,
612 params.value, params.selection_start, params.selection_end,
613 params.composition_start, params.composition_end,
614 params.show_ime_if_needed, params.is_non_ime_change);
617 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
618 SkColor color) {
619 if (cached_background_color_ == color)
620 return;
622 cached_background_color_ = color;
623 if (content_view_core_)
624 content_view_core_->OnBackgroundColorChanged(color);
627 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
628 DCHECK(!using_synchronous_compositor_);
629 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
630 "enabled", enabled);
631 if (enabled)
632 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
633 else
634 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
637 void RenderWidgetHostViewAndroid::OnStartContentIntent(
638 const GURL& content_url) {
639 if (content_view_core_)
640 content_view_core_->StartContentIntent(content_url);
643 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
644 const base::string16& text,
645 const base::string16& html,
646 const gfx::Rect rect) {
647 if (content_view_core_)
648 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
651 bool RenderWidgetHostViewAndroid::OnTouchEvent(
652 const ui::MotionEvent& event) {
653 if (!host_)
654 return false;
656 if (selection_controller_ &&
657 selection_controller_->WillHandleTouchEvent(event))
658 return true;
660 if (!gesture_provider_.OnTouchEvent(event))
661 return false;
663 if (gesture_text_selector_.OnTouchEvent(event)) {
664 gesture_provider_.OnTouchEventAck(false);
665 return true;
668 // Short-circuit touch forwarding if no touch handlers exist.
669 if (!host_->ShouldForwardTouchEvent()) {
670 const bool event_consumed = false;
671 gesture_provider_.OnTouchEventAck(event_consumed);
672 return true;
675 SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
676 return true;
679 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
680 const ui::MotionEvent& event) {
681 return selection_controller_ &&
682 selection_controller_->WillHandleTouchEvent(event);
685 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
686 const ui::MotionEvent* current_down_event =
687 gesture_provider_.GetCurrentDownEvent();
688 if (!current_down_event)
689 return;
691 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
692 DCHECK(cancel_event);
693 OnTouchEvent(*cancel_event);
695 touch_scrolling_ = false;
696 potentially_active_fling_count_ = 0;
697 OnContentScrollingChange();
700 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
701 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
704 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
705 bool enabled) {
706 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
709 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
710 ime_adapter_android_.CancelComposition();
713 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
714 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
715 if (selection_controller_)
716 selection_controller_->OnSelectionEditable(is_editable_node);
719 void RenderWidgetHostViewAndroid::RenderProcessGone(
720 base::TerminationStatus status, int error_code) {
721 Destroy();
724 void RenderWidgetHostViewAndroid::Destroy() {
725 RemoveLayers();
726 SetContentViewCore(NULL);
728 // The RenderWidgetHost's destruction led here, so don't call it.
729 host_ = NULL;
731 delete this;
734 void RenderWidgetHostViewAndroid::SetTooltipText(
735 const base::string16& tooltip_text) {
736 // Tooltips don't makes sense on Android.
739 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
740 size_t offset,
741 const gfx::Range& range) {
742 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
744 if (selection_controller_)
745 selection_controller_->OnSelectionEmpty(text.empty());
747 if (!content_view_core_)
748 return;
749 if (range.is_empty()) {
750 content_view_core_->OnSelectionChanged("");
751 return;
754 DCHECK(!text.empty());
755 size_t pos = range.GetMin() - offset;
756 size_t n = range.length();
758 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
759 if (pos >= text.length()) {
760 NOTREACHED() << "The text can not cover range.";
761 return;
764 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
766 content_view_core_->OnSelectionChanged(utf8_selection);
769 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
770 const ViewHostMsg_SelectionBounds_Params& params) {
771 if (!selection_controller_)
772 return;
774 gfx::RectF start_rect(params.anchor_rect);
775 gfx::RectF end_rect(params.focus_rect);
776 if (params.is_anchor_first)
777 std::swap(start_rect, end_rect);
779 cc::ViewportSelectionBound start_bound, end_bound;
780 start_bound.visible = true;
781 end_bound.visible = true;
782 start_bound.edge_top = start_rect.origin();
783 start_bound.edge_bottom = start_rect.bottom_left();
784 end_bound.edge_top = end_rect.origin();
785 end_bound.edge_bottom = end_rect.bottom_left();
787 if (params.anchor_rect == params.focus_rect) {
788 if (params.anchor_rect.x() && params.anchor_rect.y())
789 start_bound.type = end_bound.type = cc::SELECTION_BOUND_CENTER;
790 } else {
791 start_bound.type = params.anchor_dir == blink::WebTextDirectionRightToLeft
792 ? cc::SELECTION_BOUND_LEFT
793 : cc::SELECTION_BOUND_RIGHT;
794 end_bound.type = params.focus_dir == blink::WebTextDirectionRightToLeft
795 ? cc::SELECTION_BOUND_RIGHT
796 : cc::SELECTION_BOUND_LEFT;
799 selection_controller_->OnSelectionBoundsChanged(start_bound, end_bound);
802 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
803 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
804 host_->SetBackgroundOpaque(opaque);
807 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
808 const gfx::Rect& src_subrect,
809 const gfx::Size& dst_size,
810 const base::Callback<void(bool, const SkBitmap&)>& callback,
811 const SkColorType color_type) {
812 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
813 if ((!host_ || host_->is_hidden()) ||
814 !IsReadbackConfigSupported(color_type)) {
815 callback.Run(false, SkBitmap());
816 return;
818 base::TimeTicks start_time = base::TimeTicks::Now();
819 if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
820 callback.Run(false, SkBitmap());
821 return;
823 const gfx::Display& display =
824 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
825 float device_scale_factor = display.device_scale_factor();
826 gfx::Size dst_size_in_pixel =
827 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
828 gfx::Rect src_subrect_in_pixel =
829 ConvertRectToPixel(device_scale_factor, src_subrect);
831 if (using_synchronous_compositor_) {
832 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
833 color_type);
834 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
835 base::TimeTicks::Now() - start_time);
836 return;
839 scoped_ptr<cc::CopyOutputRequest> request;
840 scoped_refptr<cc::Layer> readback_layer;
841 DCHECK(content_view_core_);
842 DCHECK(content_view_core_->GetWindowAndroid());
843 ui::WindowAndroidCompositor* compositor =
844 content_view_core_->GetWindowAndroid()->GetCompositor();
845 DCHECK(compositor);
846 DCHECK(frame_provider_);
847 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
848 cc::DelegatedRendererLayer::Create(frame_provider_);
849 delegated_layer->SetBounds(content_size_in_layer_);
850 delegated_layer->SetHideLayerAndSubtree(true);
851 delegated_layer->SetIsDrawable(true);
852 delegated_layer->SetContentsOpaque(true);
853 compositor->AttachLayerForReadback(delegated_layer);
855 readback_layer = delegated_layer;
856 request = cc::CopyOutputRequest::CreateRequest(
857 base::Bind(&RenderWidgetHostViewAndroid::
858 PrepareTextureCopyOutputResultForDelegatedReadback,
859 dst_size_in_pixel,
860 color_type,
861 start_time,
862 readback_layer,
863 callback));
864 request->set_area(src_subrect_in_pixel);
865 readback_layer->RequestCopyOfOutput(request.Pass());
868 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
869 const gfx::Rect& src_subrect,
870 const scoped_refptr<media::VideoFrame>& target,
871 const base::Callback<void(bool)>& callback) {
872 NOTIMPLEMENTED();
873 callback.Run(false);
876 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
877 return false;
880 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
881 const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) {
882 if (!content_view_core_)
883 return;
885 content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
888 scoped_ptr<SyntheticGestureTarget>
889 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
890 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
891 host_, content_view_core_->CreateTouchEventSynthesizer()));
894 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
895 uint32 output_surface_id) {
896 DCHECK(host_);
897 cc::CompositorFrameAck ack;
898 if (resource_collection_.get())
899 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
900 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
901 output_surface_id,
902 host_->GetProcess()->GetID(),
903 ack);
906 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
907 uint32 output_surface_id) {
908 DCHECK(resource_collection_);
910 cc::CompositorFrameAck ack;
911 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
912 DCHECK(!ack.resources.empty());
914 RenderWidgetHostImpl::SendReclaimCompositorResources(
915 host_->GetRoutingID(),
916 output_surface_id,
917 host_->GetProcess()->GetID(),
918 ack);
921 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
922 if (ack_callbacks_.size())
923 return;
924 SendReturnedDelegatedResources(last_output_surface_id_);
927 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
928 RemoveLayers();
929 frame_provider_ = NULL;
930 layer_ = NULL;
931 // This gets called when ever any eviction, loosing resources, swapping
932 // problems are encountered and so we abort any pending readbacks here.
933 AbortPendingReadbackRequests();
936 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
937 uint32 output_surface_id,
938 scoped_ptr<cc::DelegatedFrameData> frame_data) {
939 bool has_content = !texture_size_in_layer_.IsEmpty();
941 if (output_surface_id != last_output_surface_id_) {
942 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
943 // any resources from the old output surface with the new output surface id.
944 if (resource_collection_.get()) {
945 resource_collection_->SetClient(NULL);
946 if (resource_collection_->LoseAllResources())
947 SendReturnedDelegatedResources(last_output_surface_id_);
948 resource_collection_ = NULL;
950 DestroyDelegatedContent();
952 last_output_surface_id_ = output_surface_id;
955 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
956 // renderer frame, assuming that the browser compositor will scale
957 // it back up to device scale. But on Android we put our browser layers in
958 // physical pixels and set our browser CC device_scale_factor to 1, so this
959 // suppresses the transform. This line may need to be removed when fixing
960 // http://crbug.com/384134 or http://crbug.com/310763
961 frame_data->device_scale_factor = 1.0f;
963 if (!has_content) {
964 DestroyDelegatedContent();
965 } else {
966 if (!resource_collection_.get()) {
967 resource_collection_ = new cc::DelegatedFrameResourceCollection;
968 resource_collection_->SetClient(this);
970 if (!frame_provider_ ||
971 texture_size_in_layer_ != frame_provider_->frame_size()) {
972 RemoveLayers();
973 frame_provider_ = new cc::DelegatedFrameProvider(
974 resource_collection_.get(), frame_data.Pass());
975 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
976 AttachLayers();
977 } else {
978 frame_provider_->SetFrameData(frame_data.Pass());
982 if (layer_.get()) {
983 layer_->SetIsDrawable(true);
984 layer_->SetContentsOpaque(true);
985 layer_->SetBounds(content_size_in_layer_);
986 layer_->SetNeedsDisplay();
989 base::Closure ack_callback =
990 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
991 weak_ptr_factory_.GetWeakPtr(),
992 output_surface_id);
994 ack_callbacks_.push(ack_callback);
995 if (host_->is_hidden())
996 RunAckCallbacks();
999 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1000 const cc::CompositorFrameMetadata& frame_metadata) {
1001 // Calculate the content size. This should be 0 if the texture_size is 0.
1002 gfx::Vector2dF offset;
1003 if (texture_size_in_layer_.IsEmpty())
1004 content_size_in_layer_ = gfx::Size();
1005 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1006 frame_metadata.scrollable_viewport_size,
1007 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1009 if (overscroll_effect_) {
1010 overscroll_effect_->UpdateDisplayParameters(
1011 CreateOverscrollDisplayParameters(frame_metadata));
1015 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1016 uint32 output_surface_id,
1017 scoped_ptr<cc::CompositorFrame> frame) {
1018 if (!frame->delegated_frame_data) {
1019 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1020 return;
1023 if (locks_on_frame_count_ > 0) {
1024 DCHECK(HasValidFrame());
1025 RetainFrame(output_surface_id, frame.Pass());
1026 return;
1029 if (layer_ && layer_->layer_tree_host()) {
1030 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1031 scoped_ptr<cc::SwapPromise> swap_promise(
1032 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1033 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1037 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1039 cc::RenderPass* root_pass =
1040 frame->delegated_frame_data->render_pass_list.back();
1041 texture_size_in_layer_ = root_pass->output_rect.size();
1042 ComputeContentsSize(frame->metadata);
1044 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1045 frame_evictor_->SwappedFrame(!host_->is_hidden());
1047 // As the metadata update may trigger view invalidation, always call it after
1048 // any potential compositor scheduling.
1049 OnFrameMetadataUpdated(frame->metadata);
1050 // Check if we have any pending readbacks, see if we have a frame available
1051 // and process them here.
1052 if (!readbacks_waiting_for_frame_.empty()) {
1053 while (!readbacks_waiting_for_frame_.empty()) {
1054 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
1055 GetScaledContentBitmap(readback_request.GetScale(),
1056 readback_request.GetColorFormat(),
1057 readback_request.GetCaptureRect(),
1058 readback_request.GetResultCallback());
1059 readbacks_waiting_for_frame_.pop();
1064 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1065 uint32 output_surface_id,
1066 scoped_ptr<cc::CompositorFrame> frame) {
1067 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1070 void RenderWidgetHostViewAndroid::RetainFrame(
1071 uint32 output_surface_id,
1072 scoped_ptr<cc::CompositorFrame> frame) {
1073 DCHECK(locks_on_frame_count_);
1075 // Store the incoming frame so that it can be swapped when all the locks have
1076 // been released. If there is already a stored frame, then replace and skip
1077 // the previous one but make sure we still eventually send the ACK. Holding
1078 // the ACK also blocks the renderer when its max_frames_pending is reached.
1079 if (last_frame_info_) {
1080 base::Closure ack_callback =
1081 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1082 weak_ptr_factory_.GetWeakPtr(),
1083 last_frame_info_->output_surface_id);
1085 ack_callbacks_.push(ack_callback);
1088 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1091 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1092 const cc::CompositorFrameMetadata& frame_metadata) {
1093 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1094 // compositor flow.
1095 OnFrameMetadataUpdated(frame_metadata);
1096 ComputeContentsSize(frame_metadata);
1098 // DevTools ScreenCast support for Android WebView.
1099 WebContents* web_contents = content_view_core_->GetWebContents();
1100 if (DevToolsAgentHost::HasFor(web_contents)) {
1101 scoped_refptr<DevToolsAgentHost> dtah =
1102 DevToolsAgentHost::GetOrCreateFor(web_contents);
1103 // Unblock the compositor.
1104 BrowserThread::PostTask(
1105 BrowserThread::UI, FROM_HERE,
1106 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
1107 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
1108 frame_metadata));
1112 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1113 if (layer_)
1114 layer_->SetContentsOpaque(!enabled);
1117 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1118 // The synchronous (WebView) compositor does not have a proper browser
1119 // compositor with which to drive animations.
1120 return !using_synchronous_compositor_;
1123 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1124 DCHECK(content_view_core_);
1125 DCHECK(!using_synchronous_compositor_);
1126 content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1129 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1130 MoveCaret(gfx::Point(position.x(), position.y()));
1133 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1134 const gfx::PointF& start,
1135 const gfx::PointF& end) {
1136 DCHECK(content_view_core_);
1137 content_view_core_->SelectBetweenCoordinates(start, end);
1140 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1141 SelectionEventType event,
1142 const gfx::PointF& position) {
1143 DCHECK(content_view_core_);
1144 content_view_core_->OnSelectionEvent(event, position);
1147 scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
1148 DCHECK(content_view_core_);
1149 if (using_synchronous_compositor_)
1150 return content_view_core_->CreatePopupTouchHandleDrawable();
1152 return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1153 content_view_core_->GetLayer(),
1154 content_view_core_->GetDpiScale(),
1155 base::android::GetApplicationContext()));
1158 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1159 const gfx::Rect& src_subrect_in_pixel,
1160 const gfx::Size& dst_size_in_pixel,
1161 const base::Callback<void(bool, const SkBitmap&)>& callback,
1162 const SkColorType color_type) {
1163 SynchronousCompositor* compositor =
1164 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1165 host_->GetRoutingID());
1166 if (!compositor) {
1167 callback.Run(false, SkBitmap());
1168 return;
1171 SkBitmap bitmap;
1172 bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1173 dst_size_in_pixel.height(),
1174 color_type,
1175 kPremul_SkAlphaType));
1176 SkCanvas canvas(bitmap);
1177 canvas.scale(
1178 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
1179 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
1180 compositor->DemandDrawSw(&canvas);
1181 callback.Run(true, bitmap);
1184 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1185 const cc::CompositorFrameMetadata& frame_metadata) {
1187 // Disable double tap zoom for pages that have a width=device-width or
1188 // narrower viewport (indicating that this is a mobile-optimized or responsive
1189 // web design, so text will be legible without zooming). Also disable
1190 // double tap and pinch for pages that prevent zooming in or out.
1191 bool has_mobile_viewport = HasMobileViewport(frame_metadata);
1192 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
1193 gesture_provider_.SetDoubleTapSupportForPageEnabled(
1194 !has_fixed_page_scale && !has_mobile_viewport);
1196 if (!content_view_core_)
1197 return;
1199 // All offsets and sizes are in CSS pixels.
1200 content_view_core_->UpdateFrameInfo(
1201 frame_metadata.root_scroll_offset,
1202 frame_metadata.page_scale_factor,
1203 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1204 frame_metadata.max_page_scale_factor),
1205 frame_metadata.root_layer_size,
1206 frame_metadata.scrollable_viewport_size,
1207 frame_metadata.location_bar_offset,
1208 frame_metadata.location_bar_content_translation);
1209 #if defined(VIDEO_HOLE)
1210 if (host_ && host_->IsRenderView()) {
1211 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1212 RenderViewHost::From(host_));
1213 rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
1215 #endif // defined(VIDEO_HOLE)
1218 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
1219 int route_id) {
1220 accelerated_surface_route_id_ = route_id;
1223 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
1224 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1225 int gpu_host_id) {
1226 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
1229 void RenderWidgetHostViewAndroid::AttachLayers() {
1230 if (!content_view_core_)
1231 return;
1232 if (!layer_.get())
1233 return;
1235 content_view_core_->AttachLayer(layer_);
1236 if (overscroll_effect_)
1237 overscroll_effect_->Enable();
1238 layer_->SetHideLayerAndSubtree(!is_showing_);
1241 void RenderWidgetHostViewAndroid::RemoveLayers() {
1242 if (!content_view_core_)
1243 return;
1245 if (!layer_.get())
1246 return;
1248 content_view_core_->RemoveLayer(layer_);
1249 if (overscroll_effect_)
1250 overscroll_effect_->Disable();
1253 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1254 // The synchronous compositor does not requre BeginFrame messages.
1255 if (using_synchronous_compositor_)
1256 requests &= FLUSH_INPUT;
1258 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1259 outstanding_vsync_requests_ |= requests;
1260 // Note that if we're not currently observing the root window, outstanding
1261 // vsync requests will be pushed if/when we resume observing in
1262 // |StartObservingRootWindow()|.
1263 if (observing_root_window_ && should_request_vsync)
1264 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1267 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1268 DCHECK(content_view_core_);
1269 if (observing_root_window_)
1270 return;
1272 observing_root_window_ = true;
1273 content_view_core_->GetWindowAndroid()->AddObserver(this);
1275 // Clear existing vsync requests to allow a request to the new window.
1276 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1277 outstanding_vsync_requests_ = 0;
1278 RequestVSyncUpdate(outstanding_vsync_requests);
1281 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1282 if (!content_view_core_) {
1283 DCHECK(!observing_root_window_);
1284 return;
1287 if (!observing_root_window_)
1288 return;
1290 observing_root_window_ = false;
1291 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1294 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1295 base::TimeDelta vsync_period) {
1296 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
1297 base::TimeTicks display_time = frame_time + vsync_period;
1299 // TODO(brianderson): Use adaptive draw-time estimation.
1300 base::TimeDelta estimated_browser_composite_time =
1301 base::TimeDelta::FromMicroseconds(
1302 (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
1304 base::TimeTicks deadline = display_time - estimated_browser_composite_time;
1306 host_->Send(new ViewMsg_BeginFrame(
1307 host_->GetRoutingID(),
1308 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
1311 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1312 bool needs_animate =
1313 overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
1314 if (selection_controller_)
1315 needs_animate |= selection_controller_->Animate(frame_time);
1316 return needs_animate;
1319 void RenderWidgetHostViewAndroid::OnContentScrollingChange() {
1320 if (selection_controller_)
1321 selection_controller_->SetTemporarilyHidden(IsContentScrolling());
1324 bool RenderWidgetHostViewAndroid::IsContentScrolling() const {
1325 return touch_scrolling_ || potentially_active_fling_count_ > 0;
1328 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
1329 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
1330 int gpu_host_id) {
1331 NOTREACHED();
1334 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
1335 NOTREACHED();
1338 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
1339 NOTREACHED();
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::NATIVE_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 switch (event.type) {
1395 case blink::WebInputEvent::GestureScrollBegin:
1396 touch_scrolling_ = true;
1397 potentially_active_fling_count_ = 0;
1398 OnContentScrollingChange();
1399 break;
1400 case blink::WebInputEvent::GestureScrollEnd:
1401 touch_scrolling_ = false;
1402 OnContentScrollingChange();
1403 break;
1404 case blink::WebInputEvent::GestureFlingStart:
1405 touch_scrolling_ = false;
1406 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
1407 ++potentially_active_fling_count_;
1408 OnContentScrollingChange();
1409 break;
1410 default:
1411 break;
1414 if (content_view_core_)
1415 content_view_core_->OnGestureEventAck(event, ack_result);
1418 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1419 const blink::WebInputEvent& input_event) {
1420 if (selection_controller_) {
1421 switch (input_event.type) {
1422 case blink::WebInputEvent::GestureLongPress:
1423 selection_controller_->OnLongPressEvent();
1424 break;
1425 case blink::WebInputEvent::GestureTap:
1426 selection_controller_->OnTapEvent();
1427 break;
1428 default:
1429 break;
1433 if (content_view_core_ &&
1434 content_view_core_->FilterInputEvent(input_event))
1435 return INPUT_EVENT_ACK_STATE_CONSUMED;
1437 if (!host_)
1438 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1440 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1441 input_event.type == blink::WebInputEvent::TouchStart) {
1442 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1443 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1444 if (shim && gpu_data && accelerated_surface_route_id_ &&
1445 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1446 shim->Send(
1447 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1450 SynchronousCompositorImpl* compositor =
1451 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1452 host_->GetRoutingID());
1453 if (compositor)
1454 return compositor->HandleInputEvent(input_event);
1455 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1458 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1459 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1460 RequestVSyncUpdate(FLUSH_INPUT);
1463 BrowserAccessibilityManager*
1464 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1465 BrowserAccessibilityDelegate* delegate) {
1466 base::android::ScopedJavaLocalRef<jobject> obj;
1467 if (content_view_core_)
1468 obj = content_view_core_->GetJavaObject();
1469 return new BrowserAccessibilityManagerAndroid(
1470 obj,
1471 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1472 delegate);
1475 bool RenderWidgetHostViewAndroid::LockMouse() {
1476 NOTIMPLEMENTED();
1477 return false;
1480 void RenderWidgetHostViewAndroid::UnlockMouse() {
1481 NOTIMPLEMENTED();
1484 // Methods called from the host to the render
1486 void RenderWidgetHostViewAndroid::SendKeyEvent(
1487 const NativeWebKeyboardEvent& event) {
1488 if (host_)
1489 host_->ForwardKeyboardEvent(event);
1492 void RenderWidgetHostViewAndroid::SendTouchEvent(
1493 const blink::WebTouchEvent& event) {
1494 if (host_)
1495 host_->ForwardTouchEventWithLatencyInfo(event, CreateLatencyInfo(event));
1497 // Send a proactive BeginFrame on the next vsync to reduce latency.
1498 // This is good enough as long as the first touch event has Begin semantics
1499 // and the actual scroll happens on the next vsync.
1500 // TODO: Is this actually still needed?
1501 if (observing_root_window_)
1502 RequestVSyncUpdate(BEGIN_FRAME);
1505 void RenderWidgetHostViewAndroid::SendMouseEvent(
1506 const blink::WebMouseEvent& event) {
1507 if (host_)
1508 host_->ForwardMouseEvent(event);
1511 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1512 const blink::WebMouseWheelEvent& event) {
1513 if (host_)
1514 host_->ForwardWheelEvent(event);
1517 void RenderWidgetHostViewAndroid::SendGestureEvent(
1518 const blink::WebGestureEvent& event) {
1519 // Sending a gesture that may trigger overscroll should resume the effect.
1520 if (overscroll_effect_)
1521 overscroll_effect_->Enable();
1523 if (host_)
1524 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1527 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1528 if (host_)
1529 host_->MoveCaret(point);
1532 void RenderWidgetHostViewAndroid::HideTextHandles() {
1533 if (selection_controller_)
1534 selection_controller_->HideAndDisallowShowingAutomatically();
1537 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1538 const gfx::PointF& point) {
1539 if (!selection_controller_)
1540 return;
1542 // As the paste popup may be triggered *before* the bounds and editability
1543 // of the region have been updated, explicitly set the properties now.
1544 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1545 // notifications are no longer required, crbug.com/398170.
1546 cc::ViewportSelectionBound insertion_bound;
1547 insertion_bound.type = cc::SELECTION_BOUND_CENTER;
1548 insertion_bound.visible = true;
1549 insertion_bound.edge_top = point;
1550 insertion_bound.edge_bottom = point;
1551 HideTextHandles();
1552 ShowSelectionHandlesAutomatically();
1553 selection_controller_->OnSelectionEditable(true);
1554 selection_controller_->OnSelectionEmpty(true);
1555 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1556 insertion_bound);
1559 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1560 return cached_background_color_;
1563 void RenderWidgetHostViewAndroid::DidOverscroll(
1564 const DidOverscrollParams& params) {
1565 if (!content_view_core_ || !layer_ || !is_showing_)
1566 return;
1568 const float device_scale_factor = content_view_core_->GetDpiScale();
1570 if (overscroll_effect_ &&
1571 overscroll_effect_->OnOverscrolled(
1572 content_view_core_->GetLayer(),
1573 base::TimeTicks::Now(),
1574 gfx::ScaleVector2d(params.accumulated_overscroll,
1575 device_scale_factor),
1576 gfx::ScaleVector2d(params.latest_overscroll_delta,
1577 device_scale_factor),
1578 gfx::ScaleVector2d(params.current_fling_velocity,
1579 device_scale_factor),
1580 gfx::ScaleVector2d(
1581 params.causal_event_viewport_point.OffsetFromOrigin(),
1582 device_scale_factor))) {
1583 SetNeedsAnimate();
1587 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1588 if (potentially_active_fling_count_) {
1589 --potentially_active_fling_count_;
1590 OnContentScrollingChange();
1593 if (content_view_core_)
1594 content_view_core_->DidStopFlinging();
1597 void RenderWidgetHostViewAndroid::SetContentViewCore(
1598 ContentViewCoreImpl* content_view_core) {
1599 RemoveLayers();
1600 StopObservingRootWindow();
1602 bool resize = false;
1603 if (content_view_core != content_view_core_) {
1604 overscroll_effect_.reset();
1605 selection_controller_.reset();
1606 ReleaseLocksOnSurface();
1607 resize = true;
1610 content_view_core_ = content_view_core;
1612 BrowserAccessibilityManager* manager = NULL;
1613 if (host_)
1614 manager = host_->GetRootBrowserAccessibilityManager();
1615 if (manager) {
1616 base::android::ScopedJavaLocalRef<jobject> obj;
1617 if (content_view_core_)
1618 obj = content_view_core_->GetJavaObject();
1619 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1622 AttachLayers();
1624 if (!content_view_core_)
1625 return;
1627 StartObservingRootWindow();
1629 if (resize)
1630 WasResized();
1632 if (!selection_controller_)
1633 selection_controller_.reset(new TouchSelectionController(this));
1635 if (overscroll_effect_enabled_ && !overscroll_effect_ &&
1636 content_view_core_->GetWindowAndroid()->GetCompositor())
1637 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1640 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1641 while (!ack_callbacks_.empty()) {
1642 ack_callbacks_.front().Run();
1643 ack_callbacks_.pop();
1647 void RenderWidgetHostViewAndroid::OnGestureEvent(
1648 const ui::GestureEventData& gesture) {
1649 if (gesture_text_selector_.OnGestureEvent(gesture))
1650 return;
1652 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
1655 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1656 RunAckCallbacks();
1660 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1661 DCHECK(content_view_core_);
1662 if (overscroll_effect_enabled_ && !overscroll_effect_)
1663 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1666 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1667 DCHECK(content_view_core_);
1668 DCHECK(!using_synchronous_compositor_);
1669 RunAckCallbacks();
1670 overscroll_effect_.reset();
1673 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1674 base::TimeDelta vsync_period) {
1675 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1676 if (!host_)
1677 return;
1679 const uint32 current_vsync_requests = outstanding_vsync_requests_;
1680 outstanding_vsync_requests_ = 0;
1682 if (current_vsync_requests & FLUSH_INPUT)
1683 host_->FlushInput();
1685 if (current_vsync_requests & BEGIN_FRAME ||
1686 current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
1687 SendBeginFrame(frame_time, vsync_period);
1690 if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
1691 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
1694 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1695 if (Animate(begin_frame_time))
1696 SetNeedsAnimate();
1699 void RenderWidgetHostViewAndroid::OnLostResources() {
1700 ReleaseLocksOnSurface();
1701 if (layer_.get())
1702 DestroyDelegatedContent();
1703 DCHECK(ack_callbacks_.empty());
1704 // We should not loose a frame if we have readback requests pending.
1705 DCHECK(readbacks_waiting_for_frame_.empty());
1708 // static
1709 void
1710 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1711 const gfx::Size& dst_size_in_pixel,
1712 const SkColorType color_type,
1713 const base::TimeTicks& start_time,
1714 scoped_refptr<cc::Layer> readback_layer,
1715 const base::Callback<void(bool, const SkBitmap&)>& callback,
1716 scoped_ptr<cc::CopyOutputResult> result) {
1717 readback_layer->RemoveFromParent();
1718 PrepareTextureCopyOutputResult(
1719 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1722 // static
1723 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1724 const gfx::Size& dst_size_in_pixel,
1725 const SkColorType color_type,
1726 const base::TimeTicks& start_time,
1727 const base::Callback<void(bool, const SkBitmap&)>& callback,
1728 scoped_ptr<cc::CopyOutputResult> result) {
1729 base::ScopedClosureRunner scoped_callback_runner(
1730 base::Bind(callback, false, SkBitmap()));
1731 TRACE_EVENT0("cc",
1732 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1734 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1735 return;
1737 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1738 if (!bitmap->allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1739 dst_size_in_pixel.height(),
1740 color_type,
1741 kOpaque_SkAlphaType)))
1742 return;
1744 ImageTransportFactoryAndroid* factory =
1745 ImageTransportFactoryAndroid::GetInstance();
1746 GLHelper* gl_helper = factory->GetGLHelper();
1748 if (!gl_helper)
1749 return;
1751 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1752 new SkAutoLockPixels(*bitmap));
1753 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1755 cc::TextureMailbox texture_mailbox;
1756 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1757 result->TakeTexture(&texture_mailbox, &release_callback);
1758 DCHECK(texture_mailbox.IsTexture());
1759 if (!texture_mailbox.IsTexture())
1760 return;
1762 ignore_result(scoped_callback_runner.Release());
1764 gl_helper->CropScaleReadbackAndCleanMailbox(
1765 texture_mailbox.mailbox(),
1766 texture_mailbox.sync_point(),
1767 result->size(),
1768 gfx::Rect(result->size()),
1769 dst_size_in_pixel,
1770 pixels,
1771 color_type,
1772 base::Bind(&CopyFromCompositingSurfaceFinished,
1773 callback,
1774 base::Passed(&release_callback),
1775 base::Passed(&bitmap),
1776 start_time,
1777 base::Passed(&bitmap_pixels_lock)),
1778 GLHelper::SCALER_QUALITY_GOOD);
1781 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1782 SkColorType color_type) {
1783 ImageTransportFactoryAndroid* factory =
1784 ImageTransportFactoryAndroid::GetInstance();
1785 GLHelper* gl_helper = factory->GetGLHelper();
1786 if (!gl_helper)
1787 return false;
1788 return gl_helper->IsReadbackConfigSupported(color_type);
1791 SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1792 // Define the criteria here. If say the 16 texture readback is
1793 // supported we should go with that (this degrades quality)
1794 // or stick back to the default format.
1795 if (base::SysInfo::IsLowEndDevice()) {
1796 if (IsReadbackConfigSupported(kRGB_565_SkColorType))
1797 return kRGB_565_SkColorType;
1799 return kN32_SkColorType;
1802 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1803 // Fake a long press to allow automatic selection handle showing.
1804 if (selection_controller_)
1805 selection_controller_->OnLongPressEvent();
1808 void RenderWidgetHostViewAndroid::SelectRange(
1809 float x1, float y1, float x2, float y2) {
1810 if (content_view_core_)
1811 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
1812 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
1815 void RenderWidgetHostViewAndroid::Unselect() {
1816 if (content_view_core_)
1817 content_view_core_->GetWebContents()->Unselect();
1820 void RenderWidgetHostViewAndroid::LongPress(
1821 base::TimeTicks time, float x, float y) {
1822 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
1823 blink::WebInputEvent::GestureLongPress,
1824 (time - base::TimeTicks()).InSecondsF(), x, y);
1825 SendGestureEvent(long_press);
1828 // static
1829 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1830 blink::WebScreenInfo* results) {
1831 const gfx::Display& display =
1832 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1833 results->rect = display.bounds();
1834 // TODO(husky): Remove any system controls from availableRect.
1835 results->availableRect = display.work_area();
1836 results->deviceScaleFactor = display.device_scale_factor();
1837 results->orientationAngle = display.RotationAsDegree();
1838 results->orientationType =
1839 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
1840 gfx::DeviceDisplayInfo info;
1841 results->depth = info.GetBitsPerPixel();
1842 results->depthPerComponent = info.GetBitsPerComponent();
1843 results->isMonochrome = (results->depthPerComponent == 0);
1846 } // namespace content