Revert of cc: Make scheduling be driven by vsync for android webview. (patchset ...
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blob76affb9aa21cdf1e2ed9d418ab125deb2f07ac72
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/layers/delegated_frame_provider.h"
21 #include "cc/layers/delegated_renderer_layer.h"
22 #include "cc/layers/layer.h"
23 #include "cc/layers/surface_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/latency_info_swap_promise.h"
29 #include "cc/output/viewport_selection_bound.h"
30 #include "cc/resources/single_release_callback.h"
31 #include "cc/surfaces/surface.h"
32 #include "cc/surfaces/surface_factory.h"
33 #include "cc/surfaces/surface_id_allocator.h"
34 #include "cc/surfaces/surface_manager.h"
35 #include "cc/trees/layer_tree_host.h"
36 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
37 #include "content/browser/android/composited_touch_handle_drawable.h"
38 #include "content/browser/android/content_view_core_impl.h"
39 #include "content/browser/android/edge_effect.h"
40 #include "content/browser/android/edge_effect_l.h"
41 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
42 #include "content/browser/android/overscroll_controller_android.h"
43 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
44 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
45 #include "content/browser/gpu/compositor_util.h"
46 #include "content/browser/gpu/gpu_data_manager_impl.h"
47 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
48 #include "content/browser/gpu/gpu_surface_tracker.h"
49 #include "content/browser/media/media_web_contents_observer.h"
50 #include "content/browser/renderer_host/compositor_impl_android.h"
51 #include "content/browser/renderer_host/dip_util.h"
52 #include "content/browser/renderer_host/frame_metadata_util.h"
53 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
54 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
55 #include "content/browser/renderer_host/input/web_input_event_util.h"
56 #include "content/browser/renderer_host/render_process_host_impl.h"
57 #include "content/browser/renderer_host/render_view_host_impl.h"
58 #include "content/browser/renderer_host/render_widget_host_impl.h"
59 #include "content/common/gpu/client/gl_helper.h"
60 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
61 #include "content/common/gpu/gpu_messages.h"
62 #include "content/common/gpu/gpu_process_launch_causes.h"
63 #include "content/common/input/did_overscroll_params.h"
64 #include "content/common/input_messages.h"
65 #include "content/common/view_messages.h"
66 #include "content/public/browser/browser_thread.h"
67 #include "content/public/browser/devtools_agent_host.h"
68 #include "content/public/browser/render_view_host.h"
69 #include "content/public/browser/render_widget_host_iterator.h"
70 #include "content/public/common/content_switches.h"
71 #include "gpu/command_buffer/client/gles2_implementation.h"
72 #include "gpu/command_buffer/client/gles2_interface.h"
73 #include "gpu/config/gpu_driver_bug_workaround_type.h"
74 #include "skia/ext/image_operations.h"
75 #include "third_party/khronos/GLES2/gl2.h"
76 #include "third_party/khronos/GLES2/gl2ext.h"
77 #include "third_party/skia/include/core/SkCanvas.h"
78 #include "ui/android/window_android.h"
79 #include "ui/android/window_android_compositor.h"
80 #include "ui/events/blink/blink_event_util.h"
81 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
82 #include "ui/events/gesture_detection/motion_event.h"
83 #include "ui/gfx/android/device_display_info.h"
84 #include "ui/gfx/android/java_bitmap.h"
85 #include "ui/gfx/android/view_configuration.h"
86 #include "ui/gfx/display.h"
87 #include "ui/gfx/geometry/dip_util.h"
88 #include "ui/gfx/geometry/size_conversions.h"
89 #include "ui/gfx/screen.h"
90 #include "ui/touch_selection/touch_selection_controller.h"
92 namespace content {
94 namespace {
96 void SatisfyCallback(cc::SurfaceManager* manager,
97 cc::SurfaceSequence sequence) {
98 std::vector<uint32_t> sequences;
99 sequences.push_back(sequence.sequence);
100 manager->DidSatisfySequences(sequence.id_namespace, &sequences);
103 void RequireCallback(cc::SurfaceManager* manager,
104 cc::SurfaceId id,
105 cc::SurfaceSequence sequence) {
106 cc::Surface* surface = manager->GetSurfaceForId(id);
107 if (!surface) {
108 LOG(ERROR) << "Attempting to require callback on nonexistent surface";
109 return;
111 surface->AddDestructionDependency(sequence);
114 const int kUndefinedOutputSurfaceId = -1;
116 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
118 // Sends an acknowledgement to the renderer of a processed IME event.
119 void SendImeEventAck(RenderWidgetHostImpl* host) {
120 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
123 class GLHelperHolder
124 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
125 public:
126 static GLHelperHolder* Create();
127 ~GLHelperHolder() override;
129 void Initialize();
131 // WebGraphicsContextLostCallback implementation.
132 virtual void onContextLost() override;
134 GLHelper* GetGLHelper() { return gl_helper_.get(); }
135 bool IsLost() { return !context_.get() || context_->isContextLost(); }
137 private:
138 GLHelperHolder();
139 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3D();
141 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
142 scoped_ptr<GLHelper> gl_helper_;
144 DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
147 GLHelperHolder* GLHelperHolder::Create() {
148 GLHelperHolder* holder = new GLHelperHolder;
149 holder->Initialize();
151 return holder;
154 GLHelperHolder::GLHelperHolder() {
157 GLHelperHolder::~GLHelperHolder() {
160 void GLHelperHolder::Initialize() {
161 context_ = CreateContext3D();
162 if (context_) {
163 context_->setContextLostCallback(this);
164 gl_helper_.reset(new GLHelper(context_->GetImplementation(),
165 context_->GetContextSupport()));
169 void GLHelperHolder::onContextLost() {
170 // Need to post a task because the command buffer client cannot be deleted
171 // from within this callback.
172 LOG(ERROR) << "Context lost.";
173 base::MessageLoop::current()->PostTask(
174 FROM_HERE,
175 base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
178 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
179 GLHelperHolder::CreateContext3D() {
180 BrowserGpuChannelHostFactory* factory =
181 BrowserGpuChannelHostFactory::instance();
182 scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
183 // GLHelper can only be used in asynchronous APIs for postprocessing after
184 // Browser Compositor operations (i.e. readback).
185 if (!gpu_channel_host.get()) {
186 // The Browser Compositor is in charge of reestablishing the channel.
187 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
190 blink::WebGraphicsContext3D::Attributes attrs;
191 attrs.shareResources = true;
192 GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
193 static const size_t kBytesPerPixel = 4;
194 gfx::DeviceDisplayInfo display_info;
195 size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
196 display_info.GetDisplayWidth() *
197 kBytesPerPixel;
198 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
199 limits.command_buffer_size = 64 * 1024;
200 limits.start_transfer_buffer_size = 64 * 1024;
201 limits.min_transfer_buffer_size = 64 * 1024;
202 limits.max_transfer_buffer_size = std::min(
203 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
204 limits.mapped_memory_reclaim_limit =
205 WebGraphicsContext3DCommandBufferImpl::kNoLimit;
206 bool lose_context_when_out_of_memory = false;
207 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
208 new WebGraphicsContext3DCommandBufferImpl(
209 0, // offscreen
210 url, gpu_channel_host.get(), attrs, lose_context_when_out_of_memory,
211 limits, nullptr));
212 if (context->InitializeOnCurrentThread()) {
213 context->traceBeginCHROMIUM(
214 "gpu_toplevel",
215 base::StringPrintf("CmdBufferImageTransportFactory-%p",
216 context.get()).c_str());
217 } else {
218 context.reset();
221 return context.Pass();
224 // This can only be used for readback postprocessing. It may return null if the
225 // channel was lost and not reestablished yet.
226 GLHelper* GetPostReadbackGLHelper() {
227 static GLHelperHolder* g_readback_helper_holder = nullptr;
229 if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) {
230 delete g_readback_helper_holder;
231 g_readback_helper_holder = nullptr;
234 if (!g_readback_helper_holder)
235 g_readback_helper_holder = GLHelperHolder::Create();
237 return g_readback_helper_holder->GetGLHelper();
240 void CopyFromCompositingSurfaceFinished(
241 ReadbackRequestCallback& callback,
242 scoped_ptr<cc::SingleReleaseCallback> release_callback,
243 scoped_ptr<SkBitmap> bitmap,
244 const base::TimeTicks& start_time,
245 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
246 bool result) {
247 TRACE_EVENT0(
248 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
249 bitmap_pixels_lock.reset();
250 uint32 sync_point = 0;
251 if (result) {
252 GLHelper* gl_helper = GetPostReadbackGLHelper();
253 if (gl_helper)
254 sync_point = gl_helper->InsertSyncPoint();
256 bool lost_resource = sync_point == 0;
257 release_callback->Run(sync_point, lost_resource);
258 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
259 base::TimeTicks::Now() - start_time);
260 ReadbackResponse response = result ? READBACK_SUCCESS : READBACK_FAILED;
261 callback.Run(*bitmap, response);
264 ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
265 ui::LatencyInfo latency_info;
266 // The latency number should only be added if the timestamp is valid.
267 if (event.timeStampSeconds) {
268 const int64 time_micros = static_cast<int64>(
269 event.timeStampSeconds * base::Time::kMicrosecondsPerSecond);
270 latency_info.AddLatencyNumberWithTimestamp(
271 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
274 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
277 return latency_info;
280 scoped_ptr<ui::TouchSelectionController> CreateSelectionController(
281 ui::TouchSelectionControllerClient* client,
282 ContentViewCore* content_view_core) {
283 DCHECK(client);
284 DCHECK(content_view_core);
285 int tap_timeout_ms = gfx::ViewConfiguration::GetTapTimeoutInMs();
286 int touch_slop_pixels = gfx::ViewConfiguration::GetTouchSlopInPixels();
287 bool show_on_tap_for_empty_editable = false;
288 return make_scoped_ptr(new ui::TouchSelectionController(
289 client,
290 base::TimeDelta::FromMilliseconds(tap_timeout_ms),
291 touch_slop_pixels / content_view_core->GetDpiScale(),
292 show_on_tap_for_empty_editable));
295 scoped_ptr<OverscrollControllerAndroid> CreateOverscrollController(
296 ContentViewCore* content_view_core) {
297 DCHECK(content_view_core);
298 ui::WindowAndroid* window = content_view_core->GetWindowAndroid();
299 DCHECK(window);
300 ui::WindowAndroidCompositor* compositor = window->GetCompositor();
301 DCHECK(compositor);
302 return make_scoped_ptr(new OverscrollControllerAndroid(
303 content_view_core->GetWebContents(),
304 compositor,
305 content_view_core->GetDpiScale()));
308 ui::GestureProvider::Config CreateGestureProviderConfig() {
309 ui::GestureProvider::Config config = ui::GetGestureProviderConfig(
310 ui::GestureProviderConfigType::CURRENT_PLATFORM);
311 config.disable_click_delay =
312 base::CommandLine::ForCurrentProcess()->HasSwitch(
313 switches::kDisableClickDelay);
314 return config;
317 ui::SelectionBound::Type ConvertSelectionBoundType(
318 cc::SelectionBoundType type) {
319 switch (type) {
320 case cc::SELECTION_BOUND_LEFT:
321 return ui::SelectionBound::LEFT;
322 case cc::SELECTION_BOUND_RIGHT:
323 return ui::SelectionBound::RIGHT;
324 case cc::SELECTION_BOUND_CENTER:
325 return ui::SelectionBound::CENTER;
326 case cc::SELECTION_BOUND_EMPTY:
327 return ui::SelectionBound::EMPTY;
329 NOTREACHED() << "Unknown selection bound type";
330 return ui::SelectionBound::EMPTY;
333 ui::SelectionBound ConvertSelectionBound(
334 const cc::ViewportSelectionBound& bound) {
335 ui::SelectionBound ui_bound;
336 ui_bound.set_type(ConvertSelectionBoundType(bound.type));
337 ui_bound.set_visible(bound.visible);
338 if (ui_bound.type() != ui::SelectionBound::EMPTY)
339 ui_bound.SetEdge(bound.edge_top, bound.edge_bottom);
340 return ui_bound;
343 } // anonymous namespace
345 ReadbackRequest::ReadbackRequest(float scale,
346 SkColorType color_type,
347 gfx::Rect src_subrect,
348 ReadbackRequestCallback& result_callback)
349 : scale_(scale),
350 color_type_(color_type),
351 src_subrect_(src_subrect),
352 result_callback_(result_callback) {
355 ReadbackRequest::ReadbackRequest() {
358 ReadbackRequest::~ReadbackRequest() {
361 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
362 uint32 output_id,
363 scoped_ptr<cc::CompositorFrame> output_frame)
364 : output_surface_id(output_id), frame(output_frame.Pass()) {}
366 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
368 void RenderWidgetHostViewAndroid::OnContextLost() {
369 scoped_ptr<RenderWidgetHostIterator> widgets(
370 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
371 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
372 if (widget->GetView()) {
373 static_cast<RenderWidgetHostViewAndroid*>(widget->GetView())
374 ->OnLostResources();
379 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
380 RenderWidgetHostImpl* widget_host,
381 ContentViewCoreImpl* content_view_core)
382 : host_(widget_host),
383 outstanding_vsync_requests_(0),
384 is_showing_(!widget_host->is_hidden()),
385 content_view_core_(NULL),
386 ime_adapter_android_(this),
387 cached_background_color_(SK_ColorWHITE),
388 last_output_surface_id_(kUndefinedOutputSurfaceId),
389 gesture_provider_(CreateGestureProviderConfig(), this),
390 stylus_text_selector_(this),
391 accelerated_surface_route_id_(0),
392 using_browser_compositor_(CompositorImpl::IsInitialized()),
393 frame_evictor_(new DelegatedFrameEvictor(this)),
394 locks_on_frame_count_(0),
395 observing_root_window_(false),
396 weak_ptr_factory_(this) {
397 host_->SetView(this);
398 SetContentViewCore(content_view_core);
401 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
402 SetContentViewCore(NULL);
403 DCHECK(ack_callbacks_.empty());
404 DCHECK(readbacks_waiting_for_frame_.empty());
405 if (resource_collection_.get())
406 resource_collection_->SetClient(NULL);
407 DCHECK(!surface_factory_);
408 DCHECK(surface_id_.is_null());
412 bool RenderWidgetHostViewAndroid::OnMessageReceived(
413 const IPC::Message& message) {
414 bool handled = true;
415 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
416 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
417 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
418 OnDidChangeBodyBackgroundColor)
419 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
420 OnSetNeedsBeginFrames)
421 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
422 OnTextInputStateChanged)
423 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
424 OnSmartClipDataExtracted)
425 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowUnhandledTapUIIfNeeded,
426 OnShowUnhandledTapUIIfNeeded)
427 IPC_MESSAGE_UNHANDLED(handled = false)
428 IPC_END_MESSAGE_MAP()
429 return handled;
432 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
433 NOTIMPLEMENTED();
436 void RenderWidgetHostViewAndroid::InitAsPopup(
437 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
438 NOTIMPLEMENTED();
441 void RenderWidgetHostViewAndroid::InitAsFullscreen(
442 RenderWidgetHostView* reference_host_view) {
443 NOTIMPLEMENTED();
446 RenderWidgetHost*
447 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
448 return host_;
451 void RenderWidgetHostViewAndroid::WasResized() {
452 host_->WasResized();
455 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
456 // Ignore the given size as only the Java code has the power to
457 // resize the view on Android.
458 default_size_ = size;
461 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
462 SetSize(rect.size());
465 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
466 while (!readbacks_waiting_for_frame_.empty()) {
467 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
468 readback_request.GetResultCallback().Run(SkBitmap(), READBACK_FAILED);
469 readbacks_waiting_for_frame_.pop();
473 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
474 float scale,
475 SkColorType color_type,
476 gfx::Rect src_subrect,
477 ReadbackRequestCallback& result_callback) {
478 if (!host_ || host_->is_hidden()) {
479 result_callback.Run(SkBitmap(), READBACK_NOT_SUPPORTED);
480 return;
482 if (!IsSurfaceAvailableForCopy()) {
483 // The view is visible, probably the frame has not yet arrived.
484 // Just add the ReadbackRequest to queue and wait for frame arrival
485 // to get this request processed.
486 readbacks_waiting_for_frame_.push(
487 ReadbackRequest(scale, color_type, src_subrect, result_callback));
488 return;
491 gfx::Size bounds = layer_->bounds();
492 if (src_subrect.IsEmpty())
493 src_subrect = gfx::Rect(bounds);
494 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
495 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
496 const gfx::Display& display =
497 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
498 float device_scale_factor = display.device_scale_factor();
499 DCHECK_GT(device_scale_factor, 0);
500 gfx::Size dst_size(
501 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
502 CopyFromCompositingSurface(
503 src_subrect, dst_size, result_callback, color_type);
506 scoped_refptr<cc::Layer> RenderWidgetHostViewAndroid::CreateDelegatedLayer()
507 const {
508 scoped_refptr<cc::Layer> delegated_layer;
509 if (!surface_id_.is_null()) {
510 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
511 DCHECK(manager);
512 // manager must outlive compositors using it.
513 scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
514 base::Bind(&SatisfyCallback, base::Unretained(manager)),
515 base::Bind(&RequireCallback, base::Unretained(manager)));
516 surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
517 delegated_layer = surface_layer;
518 } else {
519 DCHECK(frame_provider_.get());
520 delegated_layer = cc::DelegatedRendererLayer::Create(frame_provider_);
522 delegated_layer->SetBounds(content_size_in_layer_);
523 delegated_layer->SetIsDrawable(true);
524 delegated_layer->SetContentsOpaque(true);
526 return delegated_layer;
529 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
530 if (!content_view_core_)
531 return false;
532 if (!layer_.get())
533 return false;
535 if (texture_size_in_layer_.IsEmpty())
536 return false;
537 // This tell us whether a valid frame has arrived or not.
538 if (!frame_evictor_->HasFrame())
539 return false;
541 return true;
544 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
545 return last_scroll_offset_;
548 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
549 return content_view_core_->GetViewAndroid();
552 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
553 return reinterpret_cast<gfx::NativeViewId>(
554 const_cast<RenderWidgetHostViewAndroid*>(this));
557 gfx::NativeViewAccessible
558 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
559 NOTIMPLEMENTED();
560 return NULL;
563 void RenderWidgetHostViewAndroid::MovePluginWindows(
564 const std::vector<WebPluginGeometry>& moves) {
565 // We don't have plugin windows on Android. Do nothing. Note: this is called
566 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
567 // processing the corresponding message from Renderer.
570 void RenderWidgetHostViewAndroid::Focus() {
571 host_->Focus();
572 host_->SetInputMethodActive(true);
573 if (overscroll_controller_)
574 overscroll_controller_->Enable();
577 void RenderWidgetHostViewAndroid::Blur() {
578 host_->SetInputMethodActive(false);
579 host_->Blur();
580 if (overscroll_controller_)
581 overscroll_controller_->Disable();
584 bool RenderWidgetHostViewAndroid::HasFocus() const {
585 if (!content_view_core_)
586 return false; // ContentViewCore not created yet.
588 return content_view_core_->HasFocus();
591 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
592 return HasValidFrame();
595 void RenderWidgetHostViewAndroid::Show() {
596 if (is_showing_)
597 return;
599 is_showing_ = true;
600 ShowInternal();
603 void RenderWidgetHostViewAndroid::Hide() {
604 if (!is_showing_)
605 return;
607 is_showing_ = false;
609 bool hide_frontbuffer = true;
610 bool stop_observing_root_window = true;
611 HideInternal(hide_frontbuffer, stop_observing_root_window);
614 bool RenderWidgetHostViewAndroid::IsShowing() {
615 // ContentViewCoreImpl represents the native side of the Java
616 // ContentViewCore. It being NULL means that it is not attached
617 // to the View system yet, so we treat this RWHVA as hidden.
618 return is_showing_ && content_view_core_;
621 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
622 DCHECK(HasValidFrame());
623 DCHECK(host_);
624 DCHECK(frame_evictor_->HasFrame());
625 frame_evictor_->LockFrame();
626 locks_on_frame_count_++;
629 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
630 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
631 return;
633 DCHECK(HasValidFrame());
634 frame_evictor_->UnlockFrame();
635 locks_on_frame_count_--;
637 if (locks_on_frame_count_ == 0) {
638 if (last_frame_info_) {
639 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
640 last_frame_info_->frame.Pass());
641 last_frame_info_.reset();
644 if (!is_showing_ && layer_.get())
645 layer_->SetHideLayerAndSubtree(true);
649 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
650 const TextSurroundingSelectionCallback& callback) {
651 // Only one outstanding request is allowed at any given time.
652 DCHECK(!callback.is_null());
653 text_surrounding_selection_callback_ = callback;
656 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
657 const base::string16& content,
658 size_t start_offset,
659 size_t end_offset) {
660 if (text_surrounding_selection_callback_.is_null())
661 return;
662 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
663 text_surrounding_selection_callback_.Reset();
666 void RenderWidgetHostViewAndroid::OnShowUnhandledTapUIIfNeeded(int x_dip,
667 int y_dip) {
668 if (!content_view_core_)
669 return;
670 // Validate the coordinates are within the viewport.
671 gfx::Size viewport_size = content_view_core_->GetViewportSizeDip();
672 if (x_dip < 0 || x_dip > viewport_size.width() ||
673 y_dip < 0 || y_dip > viewport_size.height())
674 return;
675 content_view_core_->OnShowUnhandledTapUIIfNeeded(x_dip, y_dip);
678 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
679 if (!frame_evictor_->HasFrame()) {
680 DCHECK_EQ(locks_on_frame_count_, 0u);
681 return;
683 while (locks_on_frame_count_ > 0) {
684 UnlockCompositingSurface();
686 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
689 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
690 if (!content_view_core_)
691 return gfx::Rect(default_size_);
693 return gfx::Rect(content_view_core_->GetViewSize());
696 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
697 if (!content_view_core_)
698 return gfx::Size();
700 return content_view_core_->GetPhysicalBackingSize();
703 bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
704 if (!content_view_core_)
705 return false;
707 // Whether or not Blink's viewport size should be shrunk by the height of the
708 // URL-bar.
709 return content_view_core_->DoTopControlsShrinkBlinkSize();
712 float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
713 if (!content_view_core_)
714 return 0.f;
716 // The height of the top controls.
717 return content_view_core_->GetTopControlsHeightDip();
720 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
721 // There are no cursors on Android.
724 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
725 // Do nothing. The UI notification is handled through ContentViewClient which
726 // is TabContentsDelegate.
729 void RenderWidgetHostViewAndroid::TextInputTypeChanged(
730 ui::TextInputType type,
731 ui::TextInputMode input_mode,
732 bool can_compose_inline,
733 int flags) {
734 // Unused on Android, which uses OnTextInputChanged instead.
737 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
738 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
741 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
742 const ViewHostMsg_TextInputState_Params& params) {
743 if (selection_controller_) {
744 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
745 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
746 // while this call is present to ensure consistency with IME after
747 // navigation and tab focus changes
748 const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
749 selection_controller_->OnSelectionEditable(is_editable_node);
752 // If the change is not originated from IME (e.g. Javascript, autofill),
753 // send back the renderer an acknowledgement, regardless of how we exit from
754 // this method.
755 base::ScopedClosureRunner ack_caller;
756 if (params.is_non_ime_change)
757 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
759 if (!IsShowing())
760 return;
762 content_view_core_->UpdateImeAdapter(
763 GetNativeImeAdapter(),
764 static_cast<int>(params.type), params.flags,
765 params.value, params.selection_start, params.selection_end,
766 params.composition_start, params.composition_end,
767 params.show_ime_if_needed, params.is_non_ime_change);
770 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
771 SkColor color) {
772 if (cached_background_color_ == color)
773 return;
775 cached_background_color_ = color;
776 if (content_view_core_)
777 content_view_core_->OnBackgroundColorChanged(color);
780 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames(bool enabled) {
781 DCHECK(using_browser_compositor_);
782 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames",
783 "enabled", enabled);
784 if (enabled)
785 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
786 else
787 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
790 void RenderWidgetHostViewAndroid::OnStartContentIntent(
791 const GURL& content_url) {
792 if (content_view_core_)
793 content_view_core_->StartContentIntent(content_url);
796 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
797 const base::string16& text,
798 const base::string16& html,
799 const gfx::Rect rect) {
800 if (content_view_core_)
801 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
804 bool RenderWidgetHostViewAndroid::OnTouchEvent(
805 const ui::MotionEvent& event) {
806 if (!host_)
807 return false;
809 if (selection_controller_ &&
810 selection_controller_->WillHandleTouchEvent(event))
811 return true;
813 if (stylus_text_selector_.OnTouchEvent(event))
814 return true;
816 ui::FilteredGestureProvider::TouchHandlingResult result =
817 gesture_provider_.OnTouchEvent(event);
818 if (!result.succeeded)
819 return false;
821 blink::WebTouchEvent web_event =
822 ui::CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll);
823 host_->ForwardTouchEventWithLatencyInfo(web_event,
824 CreateLatencyInfo(web_event));
826 // Send a proactive BeginFrame on the next vsync to reduce latency.
827 // This is good enough as long as the first touch event has Begin semantics
828 // and the actual scroll happens on the next vsync.
829 if (observing_root_window_)
830 RequestVSyncUpdate(BEGIN_FRAME);
832 return true;
835 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
836 const ui::MotionEvent& event) {
837 return selection_controller_ &&
838 selection_controller_->WillHandleTouchEvent(event);
841 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
842 const ui::MotionEvent* current_down_event =
843 gesture_provider_.GetCurrentDownEvent();
844 if (current_down_event) {
845 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
846 OnTouchEvent(*cancel_event);
849 // A hard reset ensures prevention of any timer-based events.
850 gesture_provider_.ResetDetection();
853 void RenderWidgetHostViewAndroid::OnDidNavigateMainFrameToNewPage() {
854 ResetGestureDetection();
857 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
858 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
861 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
862 bool enabled) {
863 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
866 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
867 ime_adapter_android_.CancelComposition();
870 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
871 const gfx::Range& range,
872 const std::vector<gfx::Rect>& character_bounds) {
873 // TODO(yukawa): Implement this.
876 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
877 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
878 if (selection_controller_)
879 selection_controller_->OnSelectionEditable(is_editable_node);
882 void RenderWidgetHostViewAndroid::RenderProcessGone(
883 base::TerminationStatus status, int error_code) {
884 Destroy();
887 void RenderWidgetHostViewAndroid::Destroy() {
888 RemoveLayers();
889 SetContentViewCore(NULL);
891 if (!surface_id_.is_null()) {
892 DCHECK(surface_factory_.get());
893 surface_factory_->Destroy(surface_id_);
894 surface_id_ = cc::SurfaceId();
896 surface_factory_.reset();
898 // The RenderWidgetHost's destruction led here, so don't call it.
899 host_ = NULL;
901 delete this;
904 void RenderWidgetHostViewAndroid::SetTooltipText(
905 const base::string16& tooltip_text) {
906 // Tooltips don't makes sense on Android.
909 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
910 size_t offset,
911 const gfx::Range& range) {
912 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
914 if (selection_controller_)
915 selection_controller_->OnSelectionEmpty(text.empty());
917 if (!content_view_core_)
918 return;
919 if (range.is_empty()) {
920 content_view_core_->OnSelectionChanged("");
921 return;
924 DCHECK(!text.empty());
925 size_t pos = range.GetMin() - offset;
926 size_t n = range.length();
928 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
929 if (pos >= text.length()) {
930 NOTREACHED() << "The text can not cover range.";
931 return;
934 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
936 content_view_core_->OnSelectionChanged(utf8_selection);
939 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
940 const ViewHostMsg_SelectionBounds_Params& params) {
941 NOTREACHED() << "Selection bounds should be routed through the compositor.";
944 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
945 RenderWidgetHostViewBase::SetBackgroundColor(color);
946 host_->SetBackgroundOpaque(GetBackgroundOpaque());
947 OnDidChangeBodyBackgroundColor(color);
950 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
951 const gfx::Rect& src_subrect,
952 const gfx::Size& dst_size,
953 ReadbackRequestCallback& callback,
954 const SkColorType color_type) {
955 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
956 if (!host_ || host_->is_hidden()) {
957 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
958 return;
960 base::TimeTicks start_time = base::TimeTicks::Now();
961 if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
962 callback.Run(SkBitmap(), READBACK_NOT_SUPPORTED);
963 return;
965 const gfx::Display& display =
966 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
967 float device_scale_factor = display.device_scale_factor();
968 gfx::Size dst_size_in_pixel =
969 gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
970 gfx::Rect src_subrect_in_pixel =
971 gfx::ConvertRectToPixel(device_scale_factor, src_subrect);
973 if (!using_browser_compositor_) {
974 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
975 color_type);
976 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
977 base::TimeTicks::Now() - start_time);
978 return;
981 scoped_ptr<cc::CopyOutputRequest> request;
982 scoped_refptr<cc::Layer> readback_layer;
983 DCHECK(content_view_core_);
984 DCHECK(content_view_core_->GetWindowAndroid());
985 ui::WindowAndroidCompositor* compositor =
986 content_view_core_->GetWindowAndroid()->GetCompositor();
987 DCHECK(compositor);
988 DCHECK(frame_provider_.get() || !surface_id_.is_null());
989 scoped_refptr<cc::Layer> layer = CreateDelegatedLayer();
990 DCHECK(layer);
991 layer->SetHideLayerAndSubtree(true);
992 compositor->AttachLayerForReadback(layer);
994 readback_layer = layer;
995 request = cc::CopyOutputRequest::CreateRequest(
996 base::Bind(&RenderWidgetHostViewAndroid::
997 PrepareTextureCopyOutputResultForDelegatedReadback,
998 dst_size_in_pixel,
999 color_type,
1000 start_time,
1001 readback_layer,
1002 callback));
1003 if (!src_subrect_in_pixel.IsEmpty())
1004 request->set_area(src_subrect_in_pixel);
1005 readback_layer->RequestCopyOfOutput(request.Pass());
1008 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
1009 const gfx::Rect& src_subrect,
1010 const scoped_refptr<media::VideoFrame>& target,
1011 const base::Callback<void(bool)>& callback) {
1012 NOTIMPLEMENTED();
1013 callback.Run(false);
1016 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
1017 return false;
1020 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
1021 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
1022 if (!content_view_core_)
1023 return;
1025 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
1028 scoped_ptr<SyntheticGestureTarget>
1029 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
1030 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
1031 host_, content_view_core_->CreateTouchEventSynthesizer()));
1034 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
1035 uint32 output_surface_id) {
1036 DCHECK(host_);
1037 cc::CompositorFrameAck ack;
1038 if (!surface_returned_resources_.empty())
1039 ack.resources.swap(surface_returned_resources_);
1040 if (resource_collection_.get())
1041 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1042 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
1043 output_surface_id, ack));
1046 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
1047 uint32 output_surface_id) {
1048 DCHECK(host_);
1049 cc::CompositorFrameAck ack;
1050 if (!surface_returned_resources_.empty()) {
1051 ack.resources.swap(surface_returned_resources_);
1052 } else {
1053 DCHECK(resource_collection_.get());
1054 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
1057 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
1058 output_surface_id, ack));
1061 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
1062 DCHECK(surface_id_.is_null());
1063 if (ack_callbacks_.size())
1064 return;
1065 SendReturnedDelegatedResources(last_output_surface_id_);
1068 void RenderWidgetHostViewAndroid::ReturnResources(
1069 const cc::ReturnedResourceArray& resources) {
1070 if (resources.empty())
1071 return;
1072 std::copy(resources.begin(), resources.end(),
1073 std::back_inserter(surface_returned_resources_));
1074 if (!ack_callbacks_.size())
1075 SendReturnedDelegatedResources(last_output_surface_id_);
1078 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
1079 RemoveLayers();
1080 frame_provider_ = NULL;
1081 if (!surface_id_.is_null()) {
1082 DCHECK(surface_factory_.get());
1083 surface_factory_->Destroy(surface_id_);
1084 surface_id_ = cc::SurfaceId();
1086 layer_ = NULL;
1087 // This gets called when ever any eviction, loosing resources, swapping
1088 // problems are encountered and so we abort any pending readbacks here.
1089 AbortPendingReadbackRequests();
1092 void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
1093 uint32 output_surface_id) {
1094 if (output_surface_id == last_output_surface_id_)
1095 return;
1096 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1097 // any resources from the old output surface with the new output surface id.
1098 if (resource_collection_.get()) {
1099 resource_collection_->SetClient(NULL);
1100 if (resource_collection_->LoseAllResources())
1101 SendReturnedDelegatedResources(last_output_surface_id_);
1102 resource_collection_ = NULL;
1104 DestroyDelegatedContent();
1105 surface_factory_.reset();
1106 if (!surface_returned_resources_.empty())
1107 SendReturnedDelegatedResources(last_output_surface_id_);
1109 last_output_surface_id_ = output_surface_id;
1112 void RenderWidgetHostViewAndroid::SubmitFrame(
1113 scoped_ptr<cc::DelegatedFrameData> frame_data) {
1114 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
1115 if (manager) {
1116 if (!surface_factory_) {
1117 id_allocator_ = CompositorImpl::CreateSurfaceIdAllocator();
1118 surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
1120 if (surface_id_.is_null() ||
1121 texture_size_in_layer_ != current_surface_size_) {
1122 RemoveLayers();
1123 if (!surface_id_.is_null())
1124 surface_factory_->Destroy(surface_id_);
1125 surface_id_ = id_allocator_->GenerateId();
1126 surface_factory_->Create(surface_id_);
1127 layer_ = CreateDelegatedLayer();
1129 DCHECK(layer_);
1131 current_surface_size_ = texture_size_in_layer_;
1132 AttachLayers();
1134 scoped_ptr<cc::CompositorFrame> compositor_frame =
1135 make_scoped_ptr(new cc::CompositorFrame());
1136 compositor_frame->delegated_frame_data = frame_data.Pass();
1138 cc::SurfaceFactory::DrawCallback ack_callback =
1139 base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
1140 weak_ptr_factory_.GetWeakPtr());
1141 surface_factory_->SubmitFrame(surface_id_, compositor_frame.Pass(),
1142 ack_callback);
1143 } else {
1144 if (!resource_collection_.get()) {
1145 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1146 resource_collection_->SetClient(this);
1148 if (!frame_provider_.get() ||
1149 texture_size_in_layer_ != frame_provider_->frame_size()) {
1150 RemoveLayers();
1151 frame_provider_ = new cc::DelegatedFrameProvider(
1152 resource_collection_.get(), frame_data.Pass());
1153 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
1154 AttachLayers();
1155 } else {
1156 frame_provider_->SetFrameData(frame_data.Pass());
1161 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
1162 uint32 output_surface_id,
1163 scoped_ptr<cc::DelegatedFrameData> frame_data) {
1164 CheckOutputSurfaceChanged(output_surface_id);
1165 bool has_content = !texture_size_in_layer_.IsEmpty();
1167 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
1168 // renderer frame, assuming that the browser compositor will scale
1169 // it back up to device scale. But on Android we put our browser layers in
1170 // physical pixels and set our browser CC device_scale_factor to 1, so this
1171 // suppresses the transform. This line may need to be removed when fixing
1172 // http://crbug.com/384134 or http://crbug.com/310763
1173 frame_data->device_scale_factor = 1.0f;
1175 if (!has_content) {
1176 DestroyDelegatedContent();
1177 } else {
1178 SubmitFrame(frame_data.Pass());
1181 if (layer_.get()) {
1182 layer_->SetIsDrawable(true);
1183 layer_->SetContentsOpaque(true);
1184 layer_->SetBounds(content_size_in_layer_);
1185 layer_->SetNeedsDisplay();
1188 base::Closure ack_callback =
1189 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1190 weak_ptr_factory_.GetWeakPtr(),
1191 output_surface_id);
1193 ack_callbacks_.push(ack_callback);
1194 if (host_->is_hidden())
1195 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1198 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1199 const cc::CompositorFrameMetadata& frame_metadata) {
1200 // Calculate the content size. This should be 0 if the texture_size is 0.
1201 gfx::Vector2dF offset;
1202 if (texture_size_in_layer_.IsEmpty())
1203 content_size_in_layer_ = gfx::Size();
1204 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1205 frame_metadata.scrollable_viewport_size,
1206 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1210 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1211 uint32 output_surface_id,
1212 scoped_ptr<cc::CompositorFrame> frame) {
1213 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1214 if (!frame->delegated_frame_data) {
1215 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1216 return;
1219 if (locks_on_frame_count_ > 0) {
1220 DCHECK(HasValidFrame());
1221 RetainFrame(output_surface_id, frame.Pass());
1222 return;
1225 if (layer_.get() && layer_->layer_tree_host()) {
1226 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1227 scoped_ptr<cc::SwapPromise> swap_promise(
1228 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1229 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1233 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1235 cc::RenderPass* root_pass =
1236 frame->delegated_frame_data->render_pass_list.back();
1237 texture_size_in_layer_ = root_pass->output_rect.size();
1238 ComputeContentsSize(frame->metadata);
1240 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1241 frame_evictor_->SwappedFrame(!host_->is_hidden());
1243 // As the metadata update may trigger view invalidation, always call it after
1244 // any potential compositor scheduling.
1245 OnFrameMetadataUpdated(frame->metadata);
1246 // Check if we have any pending readbacks, see if we have a frame available
1247 // and process them here.
1248 if (!readbacks_waiting_for_frame_.empty()) {
1249 while (!readbacks_waiting_for_frame_.empty()) {
1250 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
1251 GetScaledContentBitmap(readback_request.GetScale(),
1252 readback_request.GetColorFormat(),
1253 readback_request.GetCaptureRect(),
1254 readback_request.GetResultCallback());
1255 readbacks_waiting_for_frame_.pop();
1260 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1261 uint32 output_surface_id,
1262 scoped_ptr<cc::CompositorFrame> frame) {
1263 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1266 void RenderWidgetHostViewAndroid::RetainFrame(
1267 uint32 output_surface_id,
1268 scoped_ptr<cc::CompositorFrame> frame) {
1269 DCHECK(locks_on_frame_count_);
1271 // Store the incoming frame so that it can be swapped when all the locks have
1272 // been released. If there is already a stored frame, then replace and skip
1273 // the previous one but make sure we still eventually send the ACK. Holding
1274 // the ACK also blocks the renderer when its max_frames_pending is reached.
1275 if (last_frame_info_) {
1276 base::Closure ack_callback =
1277 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1278 weak_ptr_factory_.GetWeakPtr(),
1279 last_frame_info_->output_surface_id);
1281 ack_callbacks_.push(ack_callback);
1284 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1287 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1288 const cc::CompositorFrameMetadata& frame_metadata) {
1289 if (!content_view_core_)
1290 return;
1292 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1293 // compositor flow.
1294 OnFrameMetadataUpdated(frame_metadata);
1295 ComputeContentsSize(frame_metadata);
1297 // DevTools ScreenCast support for Android WebView.
1298 WebContents* web_contents = content_view_core_->GetWebContents();
1299 if (DevToolsAgentHost::HasFor(web_contents)) {
1300 scoped_refptr<DevToolsAgentHost> dtah =
1301 DevToolsAgentHost::GetOrCreateFor(web_contents);
1302 // Unblock the compositor.
1303 BrowserThread::PostTask(
1304 BrowserThread::UI, FROM_HERE,
1305 base::Bind(
1306 &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
1307 static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
1308 frame_metadata));
1312 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1313 if (layer_.get())
1314 layer_->SetContentsOpaque(!enabled);
1317 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1318 // The synchronous (WebView) compositor does not have a proper browser
1319 // compositor with which to drive animations.
1320 return using_browser_compositor_;
1323 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1324 DCHECK(content_view_core_);
1325 DCHECK(using_browser_compositor_);
1326 content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1329 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1330 MoveCaret(gfx::Point(position.x(), position.y()));
1333 void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
1334 const gfx::PointF& extent) {
1335 DCHECK(content_view_core_);
1336 content_view_core_->MoveRangeSelectionExtent(extent);
1339 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1340 const gfx::PointF& base,
1341 const gfx::PointF& extent) {
1342 DCHECK(content_view_core_);
1343 content_view_core_->SelectBetweenCoordinates(base, extent);
1346 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1347 ui::SelectionEventType event,
1348 const gfx::PointF& position) {
1349 DCHECK(content_view_core_);
1350 // Showing the selection action bar can alter the current View coordinates in
1351 // such a way that the current MotionEvent stream is suddenly shifted in
1352 // space. Avoid the associated scroll jump by pre-emptively cancelling gesture
1353 // detection; scrolling after the selection is activated is unnecessary.
1354 if (event == ui::SelectionEventType::SELECTION_SHOWN)
1355 ResetGestureDetection();
1356 content_view_core_->OnSelectionEvent(event, position);
1359 scoped_ptr<ui::TouchHandleDrawable>
1360 RenderWidgetHostViewAndroid::CreateDrawable() {
1361 DCHECK(content_view_core_);
1362 if (!using_browser_compositor_)
1363 return content_view_core_->CreatePopupTouchHandleDrawable();
1365 return scoped_ptr<ui::TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1366 content_view_core_->GetLayer().get(),
1367 content_view_core_->GetDpiScale(),
1368 // Use the activity context (instead of the application context) to ensure
1369 // proper handle theming.
1370 content_view_core_->GetContext().obj()));
1373 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1374 const gfx::Rect& src_subrect_in_pixel,
1375 const gfx::Size& dst_size_in_pixel,
1376 ReadbackRequestCallback& callback,
1377 const SkColorType color_type) {
1378 gfx::Size input_size_in_pixel;
1379 if (src_subrect_in_pixel.IsEmpty())
1380 input_size_in_pixel = content_size_in_layer_;
1381 else
1382 input_size_in_pixel = src_subrect_in_pixel.size();
1384 gfx::Size output_size_in_pixel;
1385 if (dst_size_in_pixel.IsEmpty())
1386 output_size_in_pixel = input_size_in_pixel;
1387 else
1388 output_size_in_pixel = dst_size_in_pixel;
1389 int output_width = output_size_in_pixel.width();
1390 int output_height = output_size_in_pixel.height();
1392 SynchronousCompositor* compositor =
1393 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1394 host_->GetRoutingID());
1395 if (!compositor) {
1396 callback.Run(SkBitmap(), READBACK_FAILED);
1397 return;
1400 SkBitmap bitmap;
1401 bitmap.allocPixels(SkImageInfo::Make(output_width,
1402 output_height,
1403 color_type,
1404 kPremul_SkAlphaType));
1405 SkCanvas canvas(bitmap);
1406 canvas.scale(
1407 (float)output_width / (float)input_size_in_pixel.width(),
1408 (float)output_height / (float)input_size_in_pixel.height());
1409 compositor->DemandDrawSw(&canvas);
1410 callback.Run(bitmap, READBACK_SUCCESS);
1413 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1414 const cc::CompositorFrameMetadata& frame_metadata) {
1415 bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
1416 gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
1418 if (!content_view_core_)
1419 return;
1421 if (overscroll_controller_)
1422 overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
1424 if (selection_controller_) {
1425 selection_controller_->OnSelectionBoundsChanged(
1426 ConvertSelectionBound(frame_metadata.selection_start),
1427 ConvertSelectionBound(frame_metadata.selection_end));
1430 // All offsets and sizes are in CSS pixels.
1431 content_view_core_->UpdateFrameInfo(
1432 frame_metadata.root_scroll_offset,
1433 frame_metadata.page_scale_factor,
1434 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1435 frame_metadata.max_page_scale_factor),
1436 frame_metadata.root_layer_size,
1437 frame_metadata.scrollable_viewport_size,
1438 frame_metadata.location_bar_offset,
1439 frame_metadata.location_bar_content_translation,
1440 is_mobile_optimized);
1441 #if defined(VIDEO_HOLE)
1442 if (host_ && host_->IsRenderView()) {
1443 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1444 RenderViewHost::From(host_));
1445 WebContentsImpl* web_contents_impl =
1446 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvhi));
1447 if (web_contents_impl)
1448 web_contents_impl->media_web_contents_observer()->OnFrameInfoUpdated();
1450 #endif // defined(VIDEO_HOLE)
1453 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
1454 // TODO: remove need for the surface id here
1455 accelerated_surface_route_id_ = route_id;
1458 void RenderWidgetHostViewAndroid::ShowInternal() {
1459 DCHECK(is_showing_);
1460 if (!host_ || !host_->is_hidden())
1461 return;
1463 if (layer_.get())
1464 layer_->SetHideLayerAndSubtree(false);
1466 frame_evictor_->SetVisible(true);
1468 if (overscroll_controller_)
1469 overscroll_controller_->Enable();
1471 host_->WasShown(ui::LatencyInfo());
1473 if (content_view_core_) {
1474 StartObservingRootWindow();
1475 RequestVSyncUpdate(BEGIN_FRAME);
1479 void RenderWidgetHostViewAndroid::HideInternal(
1480 bool hide_frontbuffer,
1481 bool stop_observing_root_window) {
1482 if (hide_frontbuffer) {
1483 if (layer_.get() && locks_on_frame_count_ == 0)
1484 layer_->SetHideLayerAndSubtree(true);
1486 frame_evictor_->SetVisible(false);
1489 if (stop_observing_root_window)
1490 StopObservingRootWindow();
1492 if (!host_ || host_->is_hidden())
1493 return;
1495 if (overscroll_controller_)
1496 overscroll_controller_->Disable();
1498 // We don't know if we will ever get a frame if we are hiding the renderer, so
1499 // we need to cancel all requests
1500 AbortPendingReadbackRequests();
1502 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1504 // Inform the renderer that we are being hidden so it can reduce its resource
1505 // utilization.
1506 host_->WasHidden();
1509 void RenderWidgetHostViewAndroid::AttachLayers() {
1510 if (!content_view_core_)
1511 return;
1512 if (!layer_.get())
1513 return;
1515 content_view_core_->AttachLayer(layer_);
1516 if (overscroll_controller_)
1517 overscroll_controller_->Enable();
1518 layer_->SetHideLayerAndSubtree(!is_showing_);
1521 void RenderWidgetHostViewAndroid::RemoveLayers() {
1522 if (!content_view_core_)
1523 return;
1525 if (!layer_.get())
1526 return;
1528 content_view_core_->RemoveLayer(layer_);
1529 if (overscroll_controller_)
1530 overscroll_controller_->Disable();
1533 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1534 // The synchronous compositor does not requre BeginFrame messages.
1535 if (!using_browser_compositor_)
1536 requests &= FLUSH_INPUT;
1538 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1539 outstanding_vsync_requests_ |= requests;
1541 // If the host has been hidden, defer vsync requests until it is shown
1542 // again via |Show()|.
1543 if (!host_ || host_->is_hidden())
1544 return;
1546 // Note that if we're not currently observing the root window, outstanding
1547 // vsync requests will be pushed if/when we resume observing in
1548 // |StartObservingRootWindow()|.
1549 if (observing_root_window_ && should_request_vsync)
1550 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1553 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1554 DCHECK(content_view_core_);
1555 DCHECK(is_showing_);
1556 if (observing_root_window_)
1557 return;
1559 observing_root_window_ = true;
1560 content_view_core_->GetWindowAndroid()->AddObserver(this);
1562 // Clear existing vsync requests to allow a request to the new window.
1563 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1564 outstanding_vsync_requests_ = 0;
1565 RequestVSyncUpdate(outstanding_vsync_requests);
1568 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1569 if (!content_view_core_) {
1570 DCHECK(!observing_root_window_);
1571 return;
1574 if (!observing_root_window_)
1575 return;
1577 observing_root_window_ = false;
1578 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1581 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1582 base::TimeDelta vsync_period) {
1583 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1584 "frame_time_us", frame_time.ToInternalValue());
1585 base::TimeTicks display_time = frame_time + vsync_period;
1587 base::TimeTicks deadline =
1588 display_time - host_->GetEstimatedBrowserCompositeTime();
1590 host_->Send(new ViewMsg_BeginFrame(
1591 host_->GetRoutingID(),
1592 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
1593 vsync_period, cc::BeginFrameArgs::NORMAL)));
1596 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1597 bool needs_animate = false;
1598 if (overscroll_controller_) {
1599 needs_animate |= overscroll_controller_->Animate(
1600 frame_time, content_view_core_->GetLayer().get());
1602 if (selection_controller_)
1603 needs_animate |= selection_controller_->Animate(frame_time);
1604 return needs_animate;
1607 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1608 if (layer_.get())
1609 DestroyDelegatedContent();
1610 frame_evictor_->DiscardedFrame();
1611 // We are evicting the delegated frame,
1612 // so there should be no pending readback requests
1613 DCHECK(readbacks_waiting_for_frame_.empty());
1616 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1617 const gfx::Size& desired_size) {
1618 NOTREACHED();
1619 return false;
1622 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1623 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1624 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1627 // TODO(jrg): Find out the implications and answer correctly here,
1628 // as we are returning the WebView and not root window bounds.
1629 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1630 return GetViewBounds();
1633 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1634 gfx::GLSurfaceHandle handle =
1635 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
1636 if (using_browser_compositor_) {
1637 handle.parent_client_id =
1638 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
1640 return handle;
1643 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1644 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1645 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1646 gesture_provider_.OnAsyncTouchEventAck(event_consumed);
1649 void RenderWidgetHostViewAndroid::GestureEventAck(
1650 const blink::WebGestureEvent& event,
1651 InputEventAckState ack_result) {
1652 if (overscroll_controller_)
1653 overscroll_controller_->OnGestureEventAck(event, ack_result);
1655 if (content_view_core_)
1656 content_view_core_->OnGestureEventAck(event, ack_result);
1659 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1660 const blink::WebInputEvent& input_event) {
1661 if (selection_controller_) {
1662 switch (input_event.type) {
1663 case blink::WebInputEvent::GestureLongPress:
1664 selection_controller_->OnLongPressEvent();
1665 break;
1666 case blink::WebInputEvent::GestureTap:
1667 selection_controller_->OnTapEvent();
1668 break;
1669 default:
1670 break;
1674 if (overscroll_controller_ &&
1675 blink::WebInputEvent::isGestureEventType(input_event.type) &&
1676 overscroll_controller_->WillHandleGestureEvent(
1677 static_cast<const blink::WebGestureEvent&>(input_event))) {
1678 return INPUT_EVENT_ACK_STATE_CONSUMED;
1681 if (content_view_core_ &&
1682 content_view_core_->FilterInputEvent(input_event))
1683 return INPUT_EVENT_ACK_STATE_CONSUMED;
1685 if (!host_)
1686 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1688 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1689 input_event.type == blink::WebInputEvent::TouchStart) {
1690 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1691 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1692 if (shim && gpu_data && accelerated_surface_route_id_ &&
1693 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1694 shim->Send(
1695 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1698 SynchronousCompositorImpl* compositor =
1699 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1700 host_->GetRoutingID());
1701 if (compositor)
1702 return compositor->HandleInputEvent(input_event);
1703 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1706 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1707 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1708 RequestVSyncUpdate(FLUSH_INPUT);
1711 BrowserAccessibilityManager*
1712 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1713 BrowserAccessibilityDelegate* delegate) {
1714 // TODO(dmazzoni): Currently there can only be one
1715 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1716 // if there's already a BrowserAccessibilityManager for the main
1717 // frame. Eventually, in order to support cross-process iframes on
1718 // Android we'll need to add support for a
1719 // BrowserAccessibilityManager for a child frame.
1720 // http://crbug.com/423846
1721 if (!host_ || host_->GetRootBrowserAccessibilityManager())
1722 return NULL;
1724 base::android::ScopedJavaLocalRef<jobject> obj;
1725 if (content_view_core_)
1726 obj = content_view_core_->GetJavaObject();
1727 return new BrowserAccessibilityManagerAndroid(
1728 obj,
1729 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1730 delegate);
1733 bool RenderWidgetHostViewAndroid::LockMouse() {
1734 NOTIMPLEMENTED();
1735 return false;
1738 void RenderWidgetHostViewAndroid::UnlockMouse() {
1739 NOTIMPLEMENTED();
1742 // Methods called from the host to the render
1744 void RenderWidgetHostViewAndroid::SendKeyEvent(
1745 const NativeWebKeyboardEvent& event) {
1746 if (host_)
1747 host_->ForwardKeyboardEvent(event);
1750 void RenderWidgetHostViewAndroid::SendMouseEvent(
1751 const blink::WebMouseEvent& event) {
1752 if (host_)
1753 host_->ForwardMouseEvent(event);
1756 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1757 const blink::WebMouseWheelEvent& event) {
1758 if (host_)
1759 host_->ForwardWheelEvent(event);
1762 void RenderWidgetHostViewAndroid::SendGestureEvent(
1763 const blink::WebGestureEvent& event) {
1764 // Sending a gesture that may trigger overscroll should resume the effect.
1765 if (overscroll_controller_)
1766 overscroll_controller_->Enable();
1768 if (host_)
1769 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1772 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1773 if (host_)
1774 host_->MoveCaret(point);
1777 void RenderWidgetHostViewAndroid::DismissTextHandles() {
1778 if (selection_controller_)
1779 selection_controller_->HideAndDisallowShowingAutomatically();
1782 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
1783 if (selection_controller_)
1784 selection_controller_->SetTemporarilyHidden(hidden);
1787 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1788 const gfx::PointF& point) {
1789 if (!selection_controller_)
1790 return;
1792 // As the paste popup may be triggered *before* the bounds and editability
1793 // of the region have been updated, explicitly set the properties now.
1794 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1795 // notifications are no longer required, crbug.com/398170.
1796 ui::SelectionBound insertion_bound;
1797 insertion_bound.set_type(ui::SelectionBound::CENTER);
1798 insertion_bound.set_visible(true);
1799 insertion_bound.SetEdge(point, point);
1800 selection_controller_->HideAndDisallowShowingAutomatically();
1801 selection_controller_->OnSelectionEditable(true);
1802 selection_controller_->OnSelectionEmpty(true);
1803 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1804 insertion_bound);
1805 selection_controller_->AllowShowingFromCurrentSelection();
1808 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1809 return cached_background_color_;
1812 void RenderWidgetHostViewAndroid::DidOverscroll(
1813 const DidOverscrollParams& params) {
1814 if (!content_view_core_ || !layer_.get() || !is_showing_)
1815 return;
1817 if (overscroll_controller_)
1818 overscroll_controller_->OnOverscrolled(params);
1821 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1822 if (content_view_core_)
1823 content_view_core_->DidStopFlinging();
1826 void RenderWidgetHostViewAndroid::SetContentViewCore(
1827 ContentViewCoreImpl* content_view_core) {
1828 RemoveLayers();
1829 StopObservingRootWindow();
1831 bool resize = false;
1832 if (content_view_core != content_view_core_) {
1833 overscroll_controller_.reset();
1834 selection_controller_.reset();
1835 ReleaseLocksOnSurface();
1836 resize = true;
1839 content_view_core_ = content_view_core;
1841 BrowserAccessibilityManager* manager = NULL;
1842 if (host_)
1843 manager = host_->GetRootBrowserAccessibilityManager();
1844 if (manager) {
1845 base::android::ScopedJavaLocalRef<jobject> obj;
1846 if (content_view_core_)
1847 obj = content_view_core_->GetJavaObject();
1848 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1851 AttachLayers();
1853 if (!content_view_core_)
1854 return;
1856 if (is_showing_)
1857 StartObservingRootWindow();
1859 if (resize)
1860 WasResized();
1862 if (!selection_controller_)
1863 selection_controller_ = CreateSelectionController(this, content_view_core_);
1865 if (!overscroll_controller_ &&
1866 content_view_core_->GetWindowAndroid()->GetCompositor()) {
1867 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1871 void RenderWidgetHostViewAndroid::RunAckCallbacks(
1872 cc::SurfaceDrawStatus status) {
1873 while (!ack_callbacks_.empty()) {
1874 ack_callbacks_.front().Run();
1875 ack_callbacks_.pop();
1879 void RenderWidgetHostViewAndroid::OnGestureEvent(
1880 const ui::GestureEventData& gesture) {
1881 blink::WebGestureEvent web_gesture =
1882 ui::CreateWebGestureEventFromGestureEventData(gesture);
1883 // TODO(jdduke): Remove this workaround after Android fixes UiAutomator to
1884 // stop providing shift meta values to synthetic MotionEvents. This prevents
1885 // unintended shift+click interpretation of all accessibility clicks.
1886 // See crbug.com/443247.
1887 if (web_gesture.type == blink::WebInputEvent::GestureTap &&
1888 web_gesture.modifiers == blink::WebInputEvent::ShiftKey) {
1889 web_gesture.modifiers = 0;
1891 SendGestureEvent(web_gesture);
1894 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1895 RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN);
1898 void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
1899 DCHECK(is_showing_);
1900 if (visible) {
1901 ShowInternal();
1902 } else {
1903 bool hide_frontbuffer = true;
1904 bool stop_observing_root_window = false;
1905 HideInternal(hide_frontbuffer, stop_observing_root_window);
1909 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1910 DCHECK(content_view_core_);
1911 if (!overscroll_controller_)
1912 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1915 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1916 DCHECK(content_view_core_);
1917 DCHECK(using_browser_compositor_);
1918 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1919 overscroll_controller_.reset();
1922 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1923 base::TimeDelta vsync_period) {
1924 TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync");
1925 if (!host_ || host_->is_hidden())
1926 return;
1928 const uint32 current_vsync_requests = outstanding_vsync_requests_;
1929 outstanding_vsync_requests_ = 0;
1931 if (current_vsync_requests & FLUSH_INPUT)
1932 host_->FlushInput();
1934 if (current_vsync_requests & BEGIN_FRAME ||
1935 current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
1936 SendBeginFrame(frame_time, vsync_period);
1939 if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
1940 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
1943 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1944 if (Animate(begin_frame_time))
1945 SetNeedsAnimate();
1948 void RenderWidgetHostViewAndroid::OnActivityPaused() {
1949 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityPaused");
1950 DCHECK(is_showing_);
1951 bool hide_frontbuffer = false;
1952 bool stop_observing_root_window = false;
1953 HideInternal(hide_frontbuffer, stop_observing_root_window);
1956 void RenderWidgetHostViewAndroid::OnActivityResumed() {
1957 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityResumed");
1958 DCHECK(is_showing_);
1959 ShowInternal();
1962 void RenderWidgetHostViewAndroid::OnLostResources() {
1963 ReleaseLocksOnSurface();
1964 if (layer_.get())
1965 DestroyDelegatedContent();
1966 DCHECK(ack_callbacks_.empty());
1967 // We should not loose a frame if we have readback requests pending.
1968 DCHECK(readbacks_waiting_for_frame_.empty());
1971 // static
1972 void
1973 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1974 const gfx::Size& dst_size_in_pixel,
1975 const SkColorType color_type,
1976 const base::TimeTicks& start_time,
1977 scoped_refptr<cc::Layer> readback_layer,
1978 ReadbackRequestCallback& callback,
1979 scoped_ptr<cc::CopyOutputResult> result) {
1980 readback_layer->RemoveFromParent();
1981 PrepareTextureCopyOutputResult(
1982 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1985 // static
1986 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1987 const gfx::Size& dst_size_in_pixel,
1988 const SkColorType color_type,
1989 const base::TimeTicks& start_time,
1990 ReadbackRequestCallback& callback,
1991 scoped_ptr<cc::CopyOutputResult> result) {
1992 base::ScopedClosureRunner scoped_callback_runner(
1993 base::Bind(callback, SkBitmap(), READBACK_FAILED));
1994 TRACE_EVENT0("cc",
1995 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1997 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1998 return;
2000 gfx::Size output_size_in_pixel;
2001 if (dst_size_in_pixel.IsEmpty())
2002 output_size_in_pixel = result->size();
2003 else
2004 output_size_in_pixel = dst_size_in_pixel;
2006 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
2007 if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
2008 output_size_in_pixel.height(),
2009 color_type,
2010 kOpaque_SkAlphaType))) {
2011 return;
2014 GLHelper* gl_helper = GetPostReadbackGLHelper();
2015 if (!gl_helper || !gl_helper->IsReadbackConfigSupported(color_type))
2016 return;
2018 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
2019 new SkAutoLockPixels(*bitmap));
2020 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
2022 cc::TextureMailbox texture_mailbox;
2023 scoped_ptr<cc::SingleReleaseCallback> release_callback;
2024 result->TakeTexture(&texture_mailbox, &release_callback);
2025 DCHECK(texture_mailbox.IsTexture());
2026 if (!texture_mailbox.IsTexture())
2027 return;
2029 ignore_result(scoped_callback_runner.Release());
2031 gl_helper->CropScaleReadbackAndCleanMailbox(
2032 texture_mailbox.mailbox(),
2033 texture_mailbox.sync_point(),
2034 result->size(),
2035 gfx::Rect(result->size()),
2036 output_size_in_pixel,
2037 pixels,
2038 color_type,
2039 base::Bind(&CopyFromCompositingSurfaceFinished,
2040 callback,
2041 base::Passed(&release_callback),
2042 base::Passed(&bitmap),
2043 start_time,
2044 base::Passed(&bitmap_pixels_lock)),
2045 GLHelper::SCALER_QUALITY_GOOD);
2048 SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
2049 // Define the criteria here. If say the 16 texture readback is
2050 // supported we should go with that (this degrades quality)
2051 // or stick back to the default format.
2052 if (base::SysInfo::IsLowEndDevice()) {
2053 // TODO(sievers): Cannot use GLHelper here. Instead remove this API
2054 // and have CopyFromCompositingSurface() fall back to RGB8 if 565 was
2055 // requested but is not supported.
2056 GLHelper* gl_helper = GetPostReadbackGLHelper();
2057 if (gl_helper && gl_helper->IsReadbackConfigSupported(kRGB_565_SkColorType))
2058 return kRGB_565_SkColorType;
2060 return kN32_SkColorType;
2063 void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
2064 float y0,
2065 float x1,
2066 float y1) {
2067 SelectBetweenCoordinates(gfx::PointF(x0, y0), gfx::PointF(x1, y1));
2070 void RenderWidgetHostViewAndroid::OnStylusSelectUpdate(float x, float y) {
2071 MoveRangeSelectionExtent(gfx::PointF(x, y));
2074 void RenderWidgetHostViewAndroid::OnStylusSelectEnd() {
2075 if (selection_controller_)
2076 selection_controller_->AllowShowingFromCurrentSelection();
2079 void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
2080 float x,
2081 float y) {
2082 // Treat the stylus tap as a long press, activating either a word selection or
2083 // context menu depending on the targetted content.
2084 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
2085 blink::WebInputEvent::GestureLongPress,
2086 (time - base::TimeTicks()).InSecondsF(), x, y);
2087 SendGestureEvent(long_press);
2090 // static
2091 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
2092 blink::WebScreenInfo* results) {
2093 const gfx::Display& display =
2094 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
2095 results->rect = display.bounds();
2096 // TODO(husky): Remove any system controls from availableRect.
2097 results->availableRect = display.work_area();
2098 results->deviceScaleFactor = display.device_scale_factor();
2099 results->orientationAngle = display.RotationAsDegree();
2100 results->orientationType =
2101 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
2102 gfx::DeviceDisplayInfo info;
2103 results->depth = info.GetBitsPerPixel();
2104 results->depthPerComponent = info.GetBitsPerComponent();
2105 results->isMonochrome = (results->depthPerComponent == 0);
2108 } // namespace content