DevTools: cut host and port from webSocketDebuggerUrl in addition to ws:// prefix
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blobf1b29bf932cbf063ad3e0d123cb0724c30a36859
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/ui_touch_selection_helper.h"
55 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
56 #include "content/browser/renderer_host/input/web_input_event_util.h"
57 #include "content/browser/renderer_host/render_process_host_impl.h"
58 #include "content/browser/renderer_host/render_view_host_impl.h"
59 #include "content/browser/renderer_host/render_widget_host_impl.h"
60 #include "content/common/gpu/client/gl_helper.h"
61 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
62 #include "content/common/gpu/gpu_messages.h"
63 #include "content/common/gpu/gpu_process_launch_causes.h"
64 #include "content/common/input/did_overscroll_params.h"
65 #include "content/common/input_messages.h"
66 #include "content/common/view_messages.h"
67 #include "content/public/browser/android/compositor.h"
68 #include "content/public/browser/browser_thread.h"
69 #include "content/public/browser/devtools_agent_host.h"
70 #include "content/public/browser/render_view_host.h"
71 #include "content/public/browser/render_widget_host_iterator.h"
72 #include "content/public/common/content_switches.h"
73 #include "gpu/command_buffer/client/gles2_implementation.h"
74 #include "gpu/command_buffer/client/gles2_interface.h"
75 #include "gpu/config/gpu_driver_bug_workaround_type.h"
76 #include "skia/ext/image_operations.h"
77 #include "third_party/khronos/GLES2/gl2.h"
78 #include "third_party/khronos/GLES2/gl2ext.h"
79 #include "third_party/skia/include/core/SkCanvas.h"
80 #include "ui/android/window_android.h"
81 #include "ui/android/window_android_compositor.h"
82 #include "ui/events/blink/blink_event_util.h"
83 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
84 #include "ui/events/gesture_detection/motion_event.h"
85 #include "ui/gfx/android/device_display_info.h"
86 #include "ui/gfx/android/java_bitmap.h"
87 #include "ui/gfx/android/view_configuration.h"
88 #include "ui/gfx/display.h"
89 #include "ui/gfx/geometry/dip_util.h"
90 #include "ui/gfx/geometry/size_conversions.h"
91 #include "ui/gfx/screen.h"
92 #include "ui/touch_selection/touch_selection_controller.h"
94 namespace content {
96 namespace {
98 void SatisfyCallback(cc::SurfaceManager* manager,
99 cc::SurfaceSequence sequence) {
100 std::vector<uint32_t> sequences;
101 sequences.push_back(sequence.sequence);
102 manager->DidSatisfySequences(sequence.id_namespace, &sequences);
105 void RequireCallback(cc::SurfaceManager* manager,
106 cc::SurfaceId id,
107 cc::SurfaceSequence sequence) {
108 cc::Surface* surface = manager->GetSurfaceForId(id);
109 if (!surface) {
110 LOG(ERROR) << "Attempting to require callback on nonexistent surface";
111 return;
113 surface->AddDestructionDependency(sequence);
116 const int kUndefinedOutputSurfaceId = -1;
118 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
120 // Sends an acknowledgement to the renderer of a processed IME event.
121 void SendImeEventAck(RenderWidgetHostImpl* host) {
122 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
125 class GLHelperHolder
126 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
127 public:
128 static GLHelperHolder* Create();
129 ~GLHelperHolder() override;
131 void Initialize();
133 // WebGraphicsContextLostCallback implementation.
134 void onContextLost() override;
136 GLHelper* GetGLHelper() { return gl_helper_.get(); }
137 bool IsLost() { return !context_.get() || context_->isContextLost(); }
139 private:
140 GLHelperHolder();
141 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3D();
143 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
144 scoped_ptr<GLHelper> gl_helper_;
146 DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
149 GLHelperHolder* GLHelperHolder::Create() {
150 GLHelperHolder* holder = new GLHelperHolder;
151 holder->Initialize();
153 return holder;
156 GLHelperHolder::GLHelperHolder() {
159 GLHelperHolder::~GLHelperHolder() {
162 void GLHelperHolder::Initialize() {
163 context_ = CreateContext3D();
164 if (context_) {
165 context_->setContextLostCallback(this);
166 gl_helper_.reset(new GLHelper(context_->GetImplementation(),
167 context_->GetContextSupport()));
171 void GLHelperHolder::onContextLost() {
172 // Need to post a task because the command buffer client cannot be deleted
173 // from within this callback.
174 LOG(ERROR) << "Context lost.";
175 base::MessageLoop::current()->PostTask(
176 FROM_HERE,
177 base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
180 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
181 GLHelperHolder::CreateContext3D() {
182 BrowserGpuChannelHostFactory* factory =
183 BrowserGpuChannelHostFactory::instance();
184 scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
185 // GLHelper can only be used in asynchronous APIs for postprocessing after
186 // Browser Compositor operations (i.e. readback).
187 if (!gpu_channel_host.get()) {
188 // The Browser Compositor is in charge of reestablishing the channel.
189 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
192 blink::WebGraphicsContext3D::Attributes attrs;
193 attrs.shareResources = true;
194 GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
195 static const size_t kBytesPerPixel = 4;
196 gfx::DeviceDisplayInfo display_info;
197 size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
198 display_info.GetDisplayWidth() *
199 kBytesPerPixel;
200 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
201 limits.command_buffer_size = 64 * 1024;
202 limits.start_transfer_buffer_size = 64 * 1024;
203 limits.min_transfer_buffer_size = 64 * 1024;
204 limits.max_transfer_buffer_size = std::min(
205 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
206 limits.mapped_memory_reclaim_limit =
207 WebGraphicsContext3DCommandBufferImpl::kNoLimit;
208 bool lose_context_when_out_of_memory = false;
209 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
210 new WebGraphicsContext3DCommandBufferImpl(
211 0, // offscreen
212 url, gpu_channel_host.get(), attrs, lose_context_when_out_of_memory,
213 limits, nullptr));
214 context->SetContextType(BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
215 if (context->InitializeOnCurrentThread()) {
216 context->traceBeginCHROMIUM(
217 "gpu_toplevel",
218 base::StringPrintf("CmdBufferImageTransportFactory-%p",
219 context.get()).c_str());
220 } else {
221 context.reset();
224 return context.Pass();
227 // This can only be used for readback postprocessing. It may return null if the
228 // channel was lost and not reestablished yet.
229 GLHelper* GetPostReadbackGLHelper() {
230 static GLHelperHolder* g_readback_helper_holder = nullptr;
232 if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) {
233 delete g_readback_helper_holder;
234 g_readback_helper_holder = nullptr;
237 if (!g_readback_helper_holder)
238 g_readback_helper_holder = GLHelperHolder::Create();
240 return g_readback_helper_holder->GetGLHelper();
243 void CopyFromCompositingSurfaceFinished(
244 ReadbackRequestCallback& callback,
245 scoped_ptr<cc::SingleReleaseCallback> release_callback,
246 scoped_ptr<SkBitmap> bitmap,
247 const base::TimeTicks& start_time,
248 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
249 bool result) {
250 TRACE_EVENT0(
251 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
252 bitmap_pixels_lock.reset();
253 uint32 sync_point = 0;
254 if (result) {
255 GLHelper* gl_helper = GetPostReadbackGLHelper();
256 if (gl_helper)
257 sync_point = gl_helper->InsertSyncPoint();
259 bool lost_resource = sync_point == 0;
260 release_callback->Run(sync_point, lost_resource);
261 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
262 base::TimeTicks::Now() - start_time);
263 ReadbackResponse response = result ? READBACK_SUCCESS : READBACK_FAILED;
264 callback.Run(*bitmap, response);
267 scoped_ptr<ui::TouchSelectionController> CreateSelectionController(
268 ui::TouchSelectionControllerClient* client,
269 ContentViewCore* content_view_core) {
270 DCHECK(client);
271 DCHECK(content_view_core);
272 ui::TouchSelectionController::Config config;
273 config.tap_timeout = base::TimeDelta::FromMilliseconds(
274 gfx::ViewConfiguration::GetTapTimeoutInMs());
275 config.tap_slop = gfx::ViewConfiguration::GetTouchSlopInPixels() /
276 content_view_core->GetDpiScale();
277 config.show_on_tap_for_empty_editable = false;
278 config.enable_longpress_drag_selection =
279 base::CommandLine::ForCurrentProcess()->HasSwitch(
280 switches::kEnableLongpressDragSelection);
281 return make_scoped_ptr(new ui::TouchSelectionController(client, config));
284 scoped_ptr<OverscrollControllerAndroid> CreateOverscrollController(
285 ContentViewCoreImpl* content_view_core) {
286 return make_scoped_ptr(new OverscrollControllerAndroid(content_view_core));
289 ui::GestureProvider::Config CreateGestureProviderConfig() {
290 ui::GestureProvider::Config config = ui::GetGestureProviderConfig(
291 ui::GestureProviderConfigType::CURRENT_PLATFORM);
292 config.disable_click_delay =
293 base::CommandLine::ForCurrentProcess()->HasSwitch(
294 switches::kDisableClickDelay);
295 return config;
298 gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) {
299 gfx::RectF rect = controller.GetRectBetweenBounds();
300 if (rect.IsEmpty())
301 return rect;
303 rect.Union(controller.GetStartHandleRect());
304 rect.Union(controller.GetEndHandleRect());
305 return rect;
308 } // anonymous namespace
310 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
311 uint32 output_id,
312 scoped_ptr<cc::CompositorFrame> output_frame)
313 : output_surface_id(output_id), frame(output_frame.Pass()) {}
315 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
317 void RenderWidgetHostViewAndroid::OnContextLost() {
318 scoped_ptr<RenderWidgetHostIterator> widgets(
319 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
320 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
321 if (widget->GetView()) {
322 static_cast<RenderWidgetHostViewAndroid*>(widget->GetView())
323 ->OnLostResources();
328 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
329 RenderWidgetHostImpl* widget_host,
330 ContentViewCoreImpl* content_view_core)
331 : host_(widget_host),
332 outstanding_vsync_requests_(0),
333 is_showing_(!widget_host->is_hidden()),
334 content_view_core_(nullptr),
335 content_view_core_window_android_(nullptr),
336 ime_adapter_android_(this),
337 cached_background_color_(SK_ColorWHITE),
338 last_output_surface_id_(kUndefinedOutputSurfaceId),
339 gesture_provider_(CreateGestureProviderConfig(), this),
340 stylus_text_selector_(this),
341 accelerated_surface_route_id_(0),
342 using_browser_compositor_(CompositorImpl::IsInitialized()),
343 frame_evictor_(new DelegatedFrameEvictor(this)),
344 locks_on_frame_count_(0),
345 observing_root_window_(false),
346 weak_ptr_factory_(this) {
347 if (CompositorImpl::GetSurfaceManager())
348 id_allocator_ = CompositorImpl::CreateSurfaceIdAllocator();
349 host_->SetView(this);
350 SetContentViewCore(content_view_core);
353 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
354 SetContentViewCore(NULL);
355 DCHECK(ack_callbacks_.empty());
356 if (resource_collection_.get())
357 resource_collection_->SetClient(NULL);
358 DCHECK(!surface_factory_);
359 DCHECK(surface_id_.is_null());
362 void RenderWidgetHostViewAndroid::Blur() {
363 host_->SetInputMethodActive(false);
364 host_->Blur();
365 if (overscroll_controller_)
366 overscroll_controller_->Disable();
369 bool RenderWidgetHostViewAndroid::OnMessageReceived(
370 const IPC::Message& message) {
371 bool handled = true;
372 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
373 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
374 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
375 OnDidChangeBodyBackgroundColor)
376 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
377 OnSetNeedsBeginFrames)
378 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
379 OnTextInputStateChanged)
380 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
381 OnSmartClipDataExtracted)
382 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowUnhandledTapUIIfNeeded,
383 OnShowUnhandledTapUIIfNeeded)
384 IPC_MESSAGE_UNHANDLED(handled = false)
385 IPC_END_MESSAGE_MAP()
386 return handled;
389 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
390 NOTIMPLEMENTED();
393 void RenderWidgetHostViewAndroid::InitAsPopup(
394 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
395 NOTIMPLEMENTED();
398 void RenderWidgetHostViewAndroid::InitAsFullscreen(
399 RenderWidgetHostView* reference_host_view) {
400 NOTIMPLEMENTED();
403 RenderWidgetHost*
404 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
405 return host_;
408 void RenderWidgetHostViewAndroid::WasResized() {
409 host_->WasResized();
412 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
413 // Ignore the given size as only the Java code has the power to
414 // resize the view on Android.
415 default_size_ = size;
418 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
419 SetSize(rect.size());
422 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
423 float scale,
424 SkColorType preferred_color_type,
425 gfx::Rect src_subrect,
426 ReadbackRequestCallback& result_callback) {
427 if (!host_ || host_->is_hidden() || !IsSurfaceAvailableForCopy()) {
428 result_callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
429 return;
431 gfx::Size bounds = layer_->bounds();
432 if (src_subrect.IsEmpty())
433 src_subrect = gfx::Rect(bounds);
434 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
435 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
436 const gfx::Display& display =
437 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
438 float device_scale_factor = display.device_scale_factor();
439 DCHECK_GT(device_scale_factor, 0);
440 gfx::Size dst_size(
441 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
442 CopyFromCompositingSurface(src_subrect, dst_size, result_callback,
443 preferred_color_type);
446 scoped_refptr<cc::Layer> RenderWidgetHostViewAndroid::CreateDelegatedLayer()
447 const {
448 scoped_refptr<cc::Layer> delegated_layer;
449 if (!surface_id_.is_null()) {
450 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
451 DCHECK(manager);
452 // manager must outlive compositors using it.
453 scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
454 Compositor::LayerSettings(),
455 base::Bind(&SatisfyCallback, base::Unretained(manager)),
456 base::Bind(&RequireCallback, base::Unretained(manager)));
457 surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
458 delegated_layer = surface_layer;
459 } else {
460 DCHECK(frame_provider_.get());
461 delegated_layer = cc::DelegatedRendererLayer::Create(
462 Compositor::LayerSettings(), frame_provider_);
464 delegated_layer->SetBounds(content_size_in_layer_);
465 delegated_layer->SetIsDrawable(true);
466 delegated_layer->SetContentsOpaque(true);
468 return delegated_layer;
471 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
472 if (!content_view_core_)
473 return false;
474 if (!layer_.get())
475 return false;
477 if (texture_size_in_layer_.IsEmpty())
478 return false;
479 // This tell us whether a valid frame has arrived or not.
480 if (!frame_evictor_->HasFrame())
481 return false;
483 return true;
486 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
487 return last_scroll_offset_;
490 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
491 return content_view_core_->GetViewAndroid();
494 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
495 return reinterpret_cast<gfx::NativeViewId>(
496 const_cast<RenderWidgetHostViewAndroid*>(this));
499 gfx::NativeViewAccessible
500 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
501 NOTIMPLEMENTED();
502 return NULL;
505 void RenderWidgetHostViewAndroid::MovePluginWindows(
506 const std::vector<WebPluginGeometry>& moves) {
507 // We don't have plugin windows on Android. Do nothing. Note: this is called
508 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
509 // processing the corresponding message from Renderer.
512 void RenderWidgetHostViewAndroid::Focus() {
513 host_->Focus();
514 host_->SetInputMethodActive(true);
515 if (overscroll_controller_)
516 overscroll_controller_->Enable();
517 if (content_view_core_) {
518 WebContentsImpl* web_contents_impl =
519 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents());
520 if (web_contents_impl->ShowingInterstitialPage())
521 content_view_core_->ForceUpdateImeAdapter(GetNativeImeAdapter());
525 bool RenderWidgetHostViewAndroid::HasFocus() const {
526 if (!content_view_core_)
527 return false; // ContentViewCore not created yet.
529 return content_view_core_->HasFocus();
532 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
533 return HasValidFrame();
536 void RenderWidgetHostViewAndroid::Show() {
537 if (is_showing_)
538 return;
540 is_showing_ = true;
541 ShowInternal();
544 void RenderWidgetHostViewAndroid::Hide() {
545 if (!is_showing_)
546 return;
548 is_showing_ = false;
550 bool hide_frontbuffer = true;
551 bool stop_observing_root_window = true;
552 HideInternal(hide_frontbuffer, stop_observing_root_window);
555 bool RenderWidgetHostViewAndroid::IsShowing() {
556 // ContentViewCoreImpl represents the native side of the Java
557 // ContentViewCore. It being NULL means that it is not attached
558 // to the View system yet, so we treat this RWHVA as hidden.
559 return is_showing_ && content_view_core_;
562 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
563 DCHECK(HasValidFrame());
564 DCHECK(host_);
565 DCHECK(frame_evictor_->HasFrame());
566 frame_evictor_->LockFrame();
567 locks_on_frame_count_++;
570 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
571 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
572 return;
574 DCHECK(HasValidFrame());
575 frame_evictor_->UnlockFrame();
576 locks_on_frame_count_--;
578 if (locks_on_frame_count_ == 0) {
579 if (last_frame_info_) {
580 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
581 last_frame_info_->frame.Pass());
582 last_frame_info_.reset();
585 if (!is_showing_ && layer_.get())
586 layer_->SetHideLayerAndSubtree(true);
590 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
591 const TextSurroundingSelectionCallback& callback) {
592 // Only one outstanding request is allowed at any given time.
593 DCHECK(!callback.is_null());
594 text_surrounding_selection_callback_ = callback;
597 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
598 const base::string16& content,
599 size_t start_offset,
600 size_t end_offset) {
601 if (text_surrounding_selection_callback_.is_null())
602 return;
603 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
604 text_surrounding_selection_callback_.Reset();
607 void RenderWidgetHostViewAndroid::OnShowUnhandledTapUIIfNeeded(int x_dip,
608 int y_dip) {
609 if (!content_view_core_)
610 return;
611 // Validate the coordinates are within the viewport.
612 gfx::Size viewport_size = content_view_core_->GetViewportSizeDip();
613 if (x_dip < 0 || x_dip > viewport_size.width() ||
614 y_dip < 0 || y_dip > viewport_size.height())
615 return;
616 content_view_core_->OnShowUnhandledTapUIIfNeeded(x_dip, y_dip);
619 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
620 if (!frame_evictor_->HasFrame()) {
621 DCHECK_EQ(locks_on_frame_count_, 0u);
622 return;
624 while (locks_on_frame_count_ > 0) {
625 UnlockCompositingSurface();
627 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
630 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
631 if (!content_view_core_)
632 return gfx::Rect(default_size_);
634 return gfx::Rect(content_view_core_->GetViewSize());
637 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
638 if (!content_view_core_)
639 return gfx::Size();
641 return content_view_core_->GetPhysicalBackingSize();
644 bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
645 if (!content_view_core_)
646 return false;
648 // Whether or not Blink's viewport size should be shrunk by the height of the
649 // URL-bar.
650 return content_view_core_->DoTopControlsShrinkBlinkSize();
653 float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
654 if (!content_view_core_)
655 return 0.f;
657 // The height of the top controls.
658 return content_view_core_->GetTopControlsHeightDip();
661 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
662 // There are no cursors on Android.
665 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
666 // Do nothing. The UI notification is handled through ContentViewClient which
667 // is TabContentsDelegate.
670 void RenderWidgetHostViewAndroid::TextInputTypeChanged(
671 ui::TextInputType type,
672 ui::TextInputMode input_mode,
673 bool can_compose_inline,
674 int flags) {
675 // Unused on Android, which uses OnTextInputChanged instead.
678 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
679 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
682 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
683 const ViewHostMsg_TextInputState_Params& params) {
684 // If the change is not originated from IME (e.g. Javascript, autofill),
685 // send back the renderer an acknowledgement, regardless of how we exit from
686 // this method.
687 base::ScopedClosureRunner ack_caller;
688 if (params.is_non_ime_change)
689 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
691 if (!IsShowing())
692 return;
694 content_view_core_->UpdateImeAdapter(
695 GetNativeImeAdapter(),
696 static_cast<int>(params.type), params.flags,
697 params.value, params.selection_start, params.selection_end,
698 params.composition_start, params.composition_end,
699 params.show_ime_if_needed, params.is_non_ime_change);
702 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
703 SkColor color) {
704 if (cached_background_color_ == color)
705 return;
707 cached_background_color_ = color;
708 if (content_view_core_)
709 content_view_core_->OnBackgroundColorChanged(color);
712 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames(bool enabled) {
713 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames",
714 "enabled", enabled);
715 if (enabled)
716 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
717 else
718 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
721 void RenderWidgetHostViewAndroid::OnStartContentIntent(
722 const GURL& content_url) {
723 if (content_view_core_)
724 content_view_core_->StartContentIntent(content_url);
727 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
728 const base::string16& text,
729 const base::string16& html,
730 const gfx::Rect rect) {
731 if (content_view_core_)
732 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
735 bool RenderWidgetHostViewAndroid::OnTouchEvent(
736 const ui::MotionEvent& event) {
737 if (!host_)
738 return false;
740 // If a browser-based widget consumes the touch event, it's critical that
741 // touch event interception be disabled. This avoids issues with
742 // double-handling for embedder-detected gestures like side swipe.
743 if (selection_controller_ &&
744 selection_controller_->WillHandleTouchEvent(event)) {
745 RequestDisallowInterceptTouchEvent();
746 return true;
749 if (stylus_text_selector_.OnTouchEvent(event)) {
750 RequestDisallowInterceptTouchEvent();
751 return true;
754 ui::FilteredGestureProvider::TouchHandlingResult result =
755 gesture_provider_.OnTouchEvent(event);
756 if (!result.succeeded)
757 return false;
759 blink::WebTouchEvent web_event =
760 ui::CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll);
761 host_->ForwardTouchEventWithLatencyInfo(web_event, ui::LatencyInfo());
763 // Send a proactive BeginFrame for this vsync to reduce scroll latency for
764 // scroll-inducing touch events. Note that Android's Choreographer ensures
765 // that BeginFrame requests made during ACTION_MOVE dispatch will be honored
766 // in the same vsync phase.
767 if (observing_root_window_&& result.did_generate_scroll)
768 RequestVSyncUpdate(BEGIN_FRAME);
770 return true;
773 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
774 const ui::MotionEvent& event) {
775 return selection_controller_ &&
776 selection_controller_->WillHandleTouchEvent(event);
779 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
780 const ui::MotionEvent* current_down_event =
781 gesture_provider_.GetCurrentDownEvent();
782 if (!current_down_event) {
783 // A hard reset ensures prevention of any timer-based events that might fire
784 // after a touch sequence has ended.
785 gesture_provider_.ResetDetection();
786 return;
789 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
790 if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
791 bool causes_scrolling = false;
792 host_->ForwardTouchEventWithLatencyInfo(
793 ui::CreateWebTouchEventFromMotionEvent(*cancel_event, causes_scrolling),
794 ui::LatencyInfo());
798 void RenderWidgetHostViewAndroid::OnDidNavigateMainFrameToNewPage() {
799 ResetGestureDetection();
802 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
803 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
806 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
807 bool enabled) {
808 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
811 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
812 ime_adapter_android_.CancelComposition();
815 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
816 const gfx::Range& range,
817 const std::vector<gfx::Rect>& character_bounds) {
818 // TODO(yukawa): Implement this.
821 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
822 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
825 void RenderWidgetHostViewAndroid::RenderProcessGone(
826 base::TerminationStatus status, int error_code) {
827 Destroy();
830 void RenderWidgetHostViewAndroid::Destroy() {
831 RemoveLayers();
832 SetContentViewCore(NULL);
834 if (!surface_id_.is_null()) {
835 DCHECK(surface_factory_.get());
836 surface_factory_->Destroy(surface_id_);
837 surface_id_ = cc::SurfaceId();
839 surface_factory_.reset();
841 // The RenderWidgetHost's destruction led here, so don't call it.
842 host_ = NULL;
844 delete this;
847 void RenderWidgetHostViewAndroid::SetTooltipText(
848 const base::string16& tooltip_text) {
849 // Tooltips don't makes sense on Android.
852 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
853 size_t offset,
854 const gfx::Range& range) {
855 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
857 if (!content_view_core_)
858 return;
859 if (range.is_empty()) {
860 content_view_core_->OnSelectionChanged("");
861 return;
864 DCHECK(!text.empty());
865 size_t pos = range.GetMin() - offset;
866 size_t n = range.length();
868 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
869 if (pos >= text.length()) {
870 NOTREACHED() << "The text can not cover range.";
871 return;
874 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
876 content_view_core_->OnSelectionChanged(utf8_selection);
879 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
880 const ViewHostMsg_SelectionBounds_Params& params) {
881 NOTREACHED() << "Selection bounds should be routed through the compositor.";
884 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
885 RenderWidgetHostViewBase::SetBackgroundColor(color);
886 host_->SetBackgroundOpaque(GetBackgroundOpaque());
887 OnDidChangeBodyBackgroundColor(color);
890 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
891 const gfx::Rect& src_subrect,
892 const gfx::Size& dst_size,
893 ReadbackRequestCallback& callback,
894 const SkColorType preferred_color_type) {
895 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
896 if (!host_ || host_->is_hidden()) {
897 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
898 return;
900 base::TimeTicks start_time = base::TimeTicks::Now();
901 if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
902 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
903 return;
905 const gfx::Display& display =
906 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
907 float device_scale_factor = display.device_scale_factor();
908 gfx::Size dst_size_in_pixel =
909 gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
910 gfx::Rect src_subrect_in_pixel =
911 gfx::ConvertRectToPixel(device_scale_factor, src_subrect);
913 if (!using_browser_compositor_) {
914 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
915 preferred_color_type);
916 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
917 base::TimeTicks::Now() - start_time);
918 return;
921 scoped_ptr<cc::CopyOutputRequest> request;
922 scoped_refptr<cc::Layer> readback_layer;
923 DCHECK(content_view_core_window_android_);
924 ui::WindowAndroidCompositor* compositor =
925 content_view_core_window_android_->GetCompositor();
926 DCHECK(compositor);
927 DCHECK(frame_provider_.get() || !surface_id_.is_null());
928 scoped_refptr<cc::Layer> layer = CreateDelegatedLayer();
929 DCHECK(layer);
930 layer->SetHideLayerAndSubtree(true);
931 compositor->AttachLayerForReadback(layer);
933 readback_layer = layer;
934 request = cc::CopyOutputRequest::CreateRequest(
935 base::Bind(&RenderWidgetHostViewAndroid::
936 PrepareTextureCopyOutputResultForDelegatedReadback,
937 dst_size_in_pixel, preferred_color_type, start_time,
938 readback_layer, callback));
939 if (!src_subrect_in_pixel.IsEmpty())
940 request->set_area(src_subrect_in_pixel);
941 readback_layer->RequestCopyOfOutput(request.Pass());
944 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
945 const gfx::Rect& src_subrect,
946 const scoped_refptr<media::VideoFrame>& target,
947 const base::Callback<void(bool)>& callback) {
948 NOTIMPLEMENTED();
949 callback.Run(false);
952 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
953 return false;
956 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
957 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
958 if (!content_view_core_)
959 return;
961 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
964 scoped_ptr<SyntheticGestureTarget>
965 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
966 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
967 host_, content_view_core_->CreateMotionEventSynthesizer()));
970 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
971 uint32 output_surface_id) {
972 DCHECK(host_);
973 cc::CompositorFrameAck ack;
974 if (!surface_returned_resources_.empty())
975 ack.resources.swap(surface_returned_resources_);
976 if (resource_collection_.get())
977 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
978 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
979 output_surface_id, ack));
982 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
983 uint32 output_surface_id) {
984 DCHECK(host_);
985 cc::CompositorFrameAck ack;
986 if (!surface_returned_resources_.empty()) {
987 ack.resources.swap(surface_returned_resources_);
988 } else {
989 DCHECK(resource_collection_.get());
990 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
993 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
994 output_surface_id, ack));
997 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
998 DCHECK(surface_id_.is_null());
999 if (ack_callbacks_.size())
1000 return;
1001 SendReturnedDelegatedResources(last_output_surface_id_);
1004 void RenderWidgetHostViewAndroid::ReturnResources(
1005 const cc::ReturnedResourceArray& resources) {
1006 if (resources.empty())
1007 return;
1008 std::copy(resources.begin(), resources.end(),
1009 std::back_inserter(surface_returned_resources_));
1010 if (!ack_callbacks_.size())
1011 SendReturnedDelegatedResources(last_output_surface_id_);
1014 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
1015 RemoveLayers();
1016 frame_provider_ = NULL;
1017 if (!surface_id_.is_null()) {
1018 DCHECK(surface_factory_.get());
1019 surface_factory_->Destroy(surface_id_);
1020 surface_id_ = cc::SurfaceId();
1022 layer_ = NULL;
1025 void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
1026 uint32 output_surface_id) {
1027 if (output_surface_id == last_output_surface_id_)
1028 return;
1029 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1030 // any resources from the old output surface with the new output surface id.
1031 if (resource_collection_.get()) {
1032 resource_collection_->SetClient(NULL);
1033 if (resource_collection_->LoseAllResources())
1034 SendReturnedDelegatedResources(last_output_surface_id_);
1035 resource_collection_ = NULL;
1037 DestroyDelegatedContent();
1038 surface_factory_.reset();
1039 if (!surface_returned_resources_.empty())
1040 SendReturnedDelegatedResources(last_output_surface_id_);
1042 last_output_surface_id_ = output_surface_id;
1045 void RenderWidgetHostViewAndroid::SubmitFrame(
1046 scoped_ptr<cc::DelegatedFrameData> frame_data) {
1047 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
1048 if (manager) {
1049 if (!surface_factory_) {
1050 surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
1052 if (surface_id_.is_null() ||
1053 texture_size_in_layer_ != current_surface_size_) {
1054 RemoveLayers();
1055 if (!surface_id_.is_null())
1056 surface_factory_->Destroy(surface_id_);
1057 surface_id_ = id_allocator_->GenerateId();
1058 surface_factory_->Create(surface_id_);
1059 layer_ = CreateDelegatedLayer();
1061 DCHECK(layer_);
1063 current_surface_size_ = texture_size_in_layer_;
1064 AttachLayers();
1066 scoped_ptr<cc::CompositorFrame> compositor_frame =
1067 make_scoped_ptr(new cc::CompositorFrame());
1068 compositor_frame->delegated_frame_data = frame_data.Pass();
1070 cc::SurfaceFactory::DrawCallback ack_callback =
1071 base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
1072 weak_ptr_factory_.GetWeakPtr());
1073 surface_factory_->SubmitFrame(surface_id_, compositor_frame.Pass(),
1074 ack_callback);
1075 } else {
1076 if (!resource_collection_.get()) {
1077 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1078 resource_collection_->SetClient(this);
1080 if (!frame_provider_.get() ||
1081 texture_size_in_layer_ != frame_provider_->frame_size()) {
1082 RemoveLayers();
1083 frame_provider_ = new cc::DelegatedFrameProvider(
1084 resource_collection_.get(), frame_data.Pass());
1085 layer_ = cc::DelegatedRendererLayer::Create(Compositor::LayerSettings(),
1086 frame_provider_);
1087 AttachLayers();
1088 } else {
1089 frame_provider_->SetFrameData(frame_data.Pass());
1094 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
1095 uint32 output_surface_id,
1096 scoped_ptr<cc::DelegatedFrameData> frame_data) {
1097 CheckOutputSurfaceChanged(output_surface_id);
1098 bool has_content = !texture_size_in_layer_.IsEmpty();
1100 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
1101 // renderer frame, assuming that the browser compositor will scale
1102 // it back up to device scale. But on Android we put our browser layers in
1103 // physical pixels and set our browser CC device_scale_factor to 1, so this
1104 // suppresses the transform. This line may need to be removed when fixing
1105 // http://crbug.com/384134 or http://crbug.com/310763
1106 frame_data->device_scale_factor = 1.0f;
1108 if (!has_content) {
1109 DestroyDelegatedContent();
1110 } else {
1111 SubmitFrame(frame_data.Pass());
1114 if (layer_.get()) {
1115 layer_->SetIsDrawable(true);
1116 layer_->SetContentsOpaque(true);
1117 layer_->SetBounds(content_size_in_layer_);
1120 base::Closure ack_callback =
1121 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1122 weak_ptr_factory_.GetWeakPtr(),
1123 output_surface_id);
1125 ack_callbacks_.push(ack_callback);
1126 if (host_->is_hidden())
1127 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1130 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1131 const cc::CompositorFrameMetadata& frame_metadata) {
1132 // Calculate the content size. This should be 0 if the texture_size is 0.
1133 gfx::Vector2dF offset;
1134 if (texture_size_in_layer_.IsEmpty())
1135 content_size_in_layer_ = gfx::Size();
1136 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1137 frame_metadata.scrollable_viewport_size,
1138 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1142 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1143 uint32 output_surface_id,
1144 scoped_ptr<cc::CompositorFrame> frame) {
1145 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1146 if (!frame->delegated_frame_data) {
1147 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1148 return;
1151 if (locks_on_frame_count_ > 0) {
1152 DCHECK(HasValidFrame());
1153 RetainFrame(output_surface_id, frame.Pass());
1154 return;
1157 if (layer_.get() && layer_->layer_tree_host()) {
1158 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1159 scoped_ptr<cc::SwapPromise> swap_promise(
1160 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1161 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1165 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1167 cc::RenderPass* root_pass =
1168 frame->delegated_frame_data->render_pass_list.back();
1169 texture_size_in_layer_ = root_pass->output_rect.size();
1170 ComputeContentsSize(frame->metadata);
1172 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1173 frame_evictor_->SwappedFrame(!host_->is_hidden());
1175 // As the metadata update may trigger view invalidation, always call it after
1176 // any potential compositor scheduling.
1177 OnFrameMetadataUpdated(frame->metadata);
1180 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1181 uint32 output_surface_id,
1182 scoped_ptr<cc::CompositorFrame> frame) {
1183 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1186 void RenderWidgetHostViewAndroid::RetainFrame(
1187 uint32 output_surface_id,
1188 scoped_ptr<cc::CompositorFrame> frame) {
1189 DCHECK(locks_on_frame_count_);
1191 // Store the incoming frame so that it can be swapped when all the locks have
1192 // been released. If there is already a stored frame, then replace and skip
1193 // the previous one but make sure we still eventually send the ACK. Holding
1194 // the ACK also blocks the renderer when its max_frames_pending is reached.
1195 if (last_frame_info_) {
1196 base::Closure ack_callback =
1197 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1198 weak_ptr_factory_.GetWeakPtr(),
1199 last_frame_info_->output_surface_id);
1201 ack_callbacks_.push(ack_callback);
1204 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1207 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1208 const cc::CompositorFrameMetadata& frame_metadata) {
1209 if (!content_view_core_)
1210 return;
1212 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1213 // compositor flow.
1214 OnFrameMetadataUpdated(frame_metadata);
1215 ComputeContentsSize(frame_metadata);
1217 // DevTools ScreenCast support for Android WebView.
1218 WebContents* web_contents = content_view_core_->GetWebContents();
1219 if (DevToolsAgentHost::HasFor(web_contents)) {
1220 scoped_refptr<DevToolsAgentHost> dtah =
1221 DevToolsAgentHost::GetOrCreateFor(web_contents);
1222 // Unblock the compositor.
1223 BrowserThread::PostTask(
1224 BrowserThread::UI, FROM_HERE,
1225 base::Bind(
1226 &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
1227 static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
1228 frame_metadata));
1232 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1233 if (layer_.get())
1234 layer_->SetContentsOpaque(!enabled);
1237 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1238 // The synchronous (WebView) compositor does not have a proper browser
1239 // compositor with which to drive animations.
1240 return using_browser_compositor_;
1243 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1244 DCHECK(content_view_core_window_android_);
1245 DCHECK(using_browser_compositor_);
1246 content_view_core_window_android_->SetNeedsAnimate();
1249 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1250 MoveCaret(gfx::Point(position.x(), position.y()));
1253 void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
1254 const gfx::PointF& extent) {
1255 DCHECK(content_view_core_);
1256 content_view_core_->MoveRangeSelectionExtent(extent);
1259 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1260 const gfx::PointF& base,
1261 const gfx::PointF& extent) {
1262 DCHECK(content_view_core_);
1263 content_view_core_->SelectBetweenCoordinates(base, extent);
1266 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1267 ui::SelectionEventType event) {
1268 DCHECK(content_view_core_);
1269 DCHECK(selection_controller_);
1270 // If a selection drag has started, it has taken over the active touch
1271 // sequence. Immediately cancel gesture detection and any downstream touch
1272 // listeners (e.g., web content) to communicate this transfer.
1273 if (event == ui::SELECTION_SHOWN)
1274 ResetGestureDetection();
1275 content_view_core_->OnSelectionEvent(
1276 event, selection_controller_->GetStartPosition(),
1277 GetSelectionRect(*selection_controller_));
1280 scoped_ptr<ui::TouchHandleDrawable>
1281 RenderWidgetHostViewAndroid::CreateDrawable() {
1282 DCHECK(content_view_core_);
1283 if (!using_browser_compositor_)
1284 return content_view_core_->CreatePopupTouchHandleDrawable();
1286 return scoped_ptr<ui::TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1287 content_view_core_->GetLayer().get(),
1288 content_view_core_->GetDpiScale(),
1289 // Use the activity context (instead of the application context) to ensure
1290 // proper handle theming.
1291 content_view_core_->GetContext().obj()));
1294 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1295 const gfx::Rect& src_subrect_in_pixel,
1296 const gfx::Size& dst_size_in_pixel,
1297 ReadbackRequestCallback& callback,
1298 const SkColorType color_type) {
1299 gfx::Size input_size_in_pixel;
1300 if (src_subrect_in_pixel.IsEmpty())
1301 input_size_in_pixel = content_size_in_layer_;
1302 else
1303 input_size_in_pixel = src_subrect_in_pixel.size();
1305 gfx::Size output_size_in_pixel;
1306 if (dst_size_in_pixel.IsEmpty())
1307 output_size_in_pixel = input_size_in_pixel;
1308 else
1309 output_size_in_pixel = dst_size_in_pixel;
1310 int output_width = output_size_in_pixel.width();
1311 int output_height = output_size_in_pixel.height();
1313 SynchronousCompositor* compositor =
1314 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1315 host_->GetRoutingID());
1316 if (!compositor) {
1317 callback.Run(SkBitmap(), READBACK_FAILED);
1318 return;
1321 SkBitmap bitmap;
1322 bitmap.allocPixels(SkImageInfo::Make(output_width,
1323 output_height,
1324 color_type,
1325 kPremul_SkAlphaType));
1326 SkCanvas canvas(bitmap);
1327 canvas.scale(
1328 (float)output_width / (float)input_size_in_pixel.width(),
1329 (float)output_height / (float)input_size_in_pixel.height());
1330 compositor->DemandDrawSw(&canvas);
1331 callback.Run(bitmap, READBACK_SUCCESS);
1334 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1335 const cc::CompositorFrameMetadata& frame_metadata) {
1336 bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
1337 gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
1339 if (!content_view_core_)
1340 return;
1342 if (overscroll_controller_)
1343 overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
1345 if (selection_controller_) {
1346 selection_controller_->OnSelectionEditable(
1347 frame_metadata.selection.is_editable);
1348 selection_controller_->OnSelectionEmpty(
1349 frame_metadata.selection.is_empty_text_form_control);
1350 selection_controller_->OnSelectionBoundsChanged(
1351 ConvertSelectionBound(frame_metadata.selection.start),
1352 ConvertSelectionBound(frame_metadata.selection.end));
1355 // All offsets and sizes are in CSS pixels.
1356 content_view_core_->UpdateFrameInfo(
1357 frame_metadata.root_scroll_offset,
1358 frame_metadata.page_scale_factor,
1359 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1360 frame_metadata.max_page_scale_factor),
1361 frame_metadata.root_layer_size,
1362 frame_metadata.scrollable_viewport_size,
1363 frame_metadata.location_bar_offset,
1364 frame_metadata.location_bar_content_translation,
1365 is_mobile_optimized);
1366 #if defined(VIDEO_HOLE)
1367 if (host_ && host_->IsRenderView()) {
1368 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1369 RenderViewHost::From(host_));
1370 WebContentsImpl* web_contents_impl =
1371 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvhi));
1372 if (web_contents_impl)
1373 web_contents_impl->media_web_contents_observer()->OnFrameInfoUpdated();
1375 #endif // defined(VIDEO_HOLE)
1378 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
1379 // TODO: remove need for the surface id here
1380 accelerated_surface_route_id_ = route_id;
1383 void RenderWidgetHostViewAndroid::ShowInternal() {
1384 DCHECK(is_showing_);
1385 if (!host_ || !host_->is_hidden())
1386 return;
1388 if (layer_.get())
1389 layer_->SetHideLayerAndSubtree(false);
1391 frame_evictor_->SetVisible(true);
1393 if (overscroll_controller_)
1394 overscroll_controller_->Enable();
1396 host_->WasShown(ui::LatencyInfo());
1398 if (content_view_core_) {
1399 StartObservingRootWindow();
1400 RequestVSyncUpdate(BEGIN_FRAME);
1404 void RenderWidgetHostViewAndroid::HideInternal(
1405 bool hide_frontbuffer,
1406 bool stop_observing_root_window) {
1407 if (hide_frontbuffer) {
1408 if (layer_.get() && locks_on_frame_count_ == 0)
1409 layer_->SetHideLayerAndSubtree(true);
1411 frame_evictor_->SetVisible(false);
1414 if (stop_observing_root_window)
1415 StopObservingRootWindow();
1417 if (!host_ || host_->is_hidden())
1418 return;
1420 if (overscroll_controller_)
1421 overscroll_controller_->Disable();
1423 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1425 // Inform the renderer that we are being hidden so it can reduce its resource
1426 // utilization.
1427 host_->WasHidden();
1430 void RenderWidgetHostViewAndroid::AttachLayers() {
1431 if (!content_view_core_)
1432 return;
1433 if (!layer_.get())
1434 return;
1436 content_view_core_->AttachLayer(layer_);
1437 if (overscroll_controller_)
1438 overscroll_controller_->Enable();
1439 layer_->SetHideLayerAndSubtree(!is_showing_);
1442 void RenderWidgetHostViewAndroid::RemoveLayers() {
1443 if (!content_view_core_)
1444 return;
1446 if (!layer_.get())
1447 return;
1449 content_view_core_->RemoveLayer(layer_);
1450 if (overscroll_controller_)
1451 overscroll_controller_->Disable();
1454 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1455 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1456 outstanding_vsync_requests_ |= requests;
1458 // If the host has been hidden, defer vsync requests until it is shown
1459 // again via |Show()|.
1460 if (!host_ || host_->is_hidden())
1461 return;
1463 // Note that if we're not currently observing the root window, outstanding
1464 // vsync requests will be pushed if/when we resume observing in
1465 // |StartObservingRootWindow()|.
1466 if (observing_root_window_ && should_request_vsync)
1467 content_view_core_window_android_->RequestVSyncUpdate();
1470 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1471 DCHECK(content_view_core_window_android_);
1472 DCHECK(is_showing_);
1473 if (observing_root_window_)
1474 return;
1476 observing_root_window_ = true;
1477 content_view_core_window_android_->AddObserver(this);
1479 // Clear existing vsync requests to allow a request to the new window.
1480 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1481 outstanding_vsync_requests_ = 0;
1482 RequestVSyncUpdate(outstanding_vsync_requests);
1485 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1486 if (!content_view_core_window_android_) {
1487 DCHECK(!observing_root_window_);
1488 return;
1491 if (!observing_root_window_)
1492 return;
1494 observing_root_window_ = false;
1495 content_view_core_window_android_->RemoveObserver(this);
1498 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1499 base::TimeDelta vsync_period) {
1500 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1501 "frame_time_us", frame_time.ToInternalValue());
1503 if (using_browser_compositor_) {
1504 base::TimeTicks display_time = frame_time + vsync_period;
1506 base::TimeTicks deadline =
1507 display_time - host_->GetEstimatedBrowserCompositeTime();
1509 host_->Send(new ViewMsg_BeginFrame(
1510 host_->GetRoutingID(),
1511 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
1512 vsync_period, cc::BeginFrameArgs::NORMAL)));
1513 } else {
1514 SynchronousCompositorImpl* compositor = SynchronousCompositorImpl::FromID(
1515 host_->GetProcess()->GetID(), host_->GetRoutingID());
1516 if (compositor) {
1517 // The synchronous compositor synchronously does it's work in this call.
1518 // It does not use a deadline.
1519 compositor->BeginFrame(cc::BeginFrameArgs::Create(
1520 BEGINFRAME_FROM_HERE, frame_time, base::TimeTicks(), vsync_period,
1521 cc::BeginFrameArgs::NORMAL));
1526 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1527 bool needs_animate = false;
1528 if (overscroll_controller_) {
1529 needs_animate |= overscroll_controller_->Animate(
1530 frame_time, content_view_core_->GetLayer().get());
1532 if (selection_controller_)
1533 needs_animate |= selection_controller_->Animate(frame_time);
1534 return needs_animate;
1537 void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
1538 if (content_view_core_)
1539 content_view_core_->RequestDisallowInterceptTouchEvent();
1542 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1543 if (layer_.get())
1544 DestroyDelegatedContent();
1545 frame_evictor_->DiscardedFrame();
1548 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1549 const gfx::Size& desired_size) {
1550 NOTREACHED();
1551 return false;
1554 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1555 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1556 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1559 // TODO(jrg): Find out the implications and answer correctly here,
1560 // as we are returning the WebView and not root window bounds.
1561 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1562 return GetViewBounds();
1565 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1566 gfx::GLSurfaceHandle handle =
1567 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
1568 if (using_browser_compositor_) {
1569 handle.parent_client_id =
1570 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
1572 return handle;
1575 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1576 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1577 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1578 gesture_provider_.OnTouchEventAck(touch.event.uniqueTouchEventId,
1579 event_consumed);
1582 void RenderWidgetHostViewAndroid::GestureEventAck(
1583 const blink::WebGestureEvent& event,
1584 InputEventAckState ack_result) {
1585 if (overscroll_controller_)
1586 overscroll_controller_->OnGestureEventAck(event, ack_result);
1588 if (content_view_core_)
1589 content_view_core_->OnGestureEventAck(event, ack_result);
1592 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1593 const blink::WebInputEvent& input_event) {
1594 if (selection_controller_ &&
1595 blink::WebInputEvent::isGestureEventType(input_event.type)) {
1596 const blink::WebGestureEvent& gesture_event =
1597 static_cast<const blink::WebGestureEvent&>(input_event);
1598 switch (gesture_event.type) {
1599 case blink::WebInputEvent::GestureLongPress:
1600 if (selection_controller_->WillHandleLongPressEvent(
1601 base::TimeTicks() +
1602 base::TimeDelta::FromSecondsD(input_event.timeStampSeconds),
1603 gfx::PointF(gesture_event.x, gesture_event.y))) {
1604 return INPUT_EVENT_ACK_STATE_CONSUMED;
1606 break;
1608 case blink::WebInputEvent::GestureTap:
1609 if (selection_controller_->WillHandleTapEvent(
1610 gfx::PointF(gesture_event.x, gesture_event.y))) {
1611 return INPUT_EVENT_ACK_STATE_CONSUMED;
1613 break;
1615 default:
1616 break;
1620 if (overscroll_controller_ &&
1621 blink::WebInputEvent::isGestureEventType(input_event.type) &&
1622 overscroll_controller_->WillHandleGestureEvent(
1623 static_cast<const blink::WebGestureEvent&>(input_event))) {
1624 return INPUT_EVENT_ACK_STATE_CONSUMED;
1627 if (content_view_core_ && content_view_core_->FilterInputEvent(input_event))
1628 return INPUT_EVENT_ACK_STATE_CONSUMED;
1630 if (!host_)
1631 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1633 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1634 input_event.type == blink::WebInputEvent::TouchStart) {
1635 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1636 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1637 if (shim && gpu_data && accelerated_surface_route_id_ &&
1638 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1639 shim->Send(
1640 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1643 SynchronousCompositorImpl* compositor =
1644 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1645 host_->GetRoutingID());
1646 if (compositor)
1647 return compositor->HandleInputEvent(input_event);
1648 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1651 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1652 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1653 RequestVSyncUpdate(FLUSH_INPUT);
1656 BrowserAccessibilityManager*
1657 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1658 BrowserAccessibilityDelegate* delegate) {
1659 // TODO(dmazzoni): Currently there can only be one
1660 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1661 // if there's already a BrowserAccessibilityManager for the main
1662 // frame. Eventually, in order to support cross-process iframes on
1663 // Android we'll need to add support for a
1664 // BrowserAccessibilityManager for a child frame.
1665 // http://crbug.com/423846
1666 if (!host_ || host_->GetRootBrowserAccessibilityManager())
1667 return NULL;
1669 base::android::ScopedJavaLocalRef<jobject> obj;
1670 if (content_view_core_)
1671 obj = content_view_core_->GetJavaObject();
1672 return new BrowserAccessibilityManagerAndroid(
1673 obj,
1674 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1675 delegate);
1678 bool RenderWidgetHostViewAndroid::LockMouse() {
1679 NOTIMPLEMENTED();
1680 return false;
1683 void RenderWidgetHostViewAndroid::UnlockMouse() {
1684 NOTIMPLEMENTED();
1687 // Methods called from the host to the render
1689 void RenderWidgetHostViewAndroid::SendKeyEvent(
1690 const NativeWebKeyboardEvent& event) {
1691 if (host_)
1692 host_->ForwardKeyboardEvent(event);
1695 void RenderWidgetHostViewAndroid::SendMouseEvent(
1696 const blink::WebMouseEvent& event) {
1697 if (host_)
1698 host_->ForwardMouseEvent(event);
1701 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1702 const blink::WebMouseWheelEvent& event) {
1703 if (host_)
1704 host_->ForwardWheelEvent(event);
1707 void RenderWidgetHostViewAndroid::SendGestureEvent(
1708 const blink::WebGestureEvent& event) {
1709 // Sending a gesture that may trigger overscroll should resume the effect.
1710 if (overscroll_controller_)
1711 overscroll_controller_->Enable();
1713 if (host_)
1714 host_->ForwardGestureEventWithLatencyInfo(event, ui::LatencyInfo());
1717 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1718 if (host_)
1719 host_->MoveCaret(point);
1722 void RenderWidgetHostViewAndroid::DismissTextHandles() {
1723 if (selection_controller_)
1724 selection_controller_->HideAndDisallowShowingAutomatically();
1727 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
1728 if (selection_controller_)
1729 selection_controller_->SetTemporarilyHidden(hidden);
1732 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1733 const gfx::PointF& point) {
1734 if (!selection_controller_)
1735 return;
1737 // As the paste popup may be triggered *before* the bounds and editability
1738 // of the region have been updated, explicitly set the properties now.
1739 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1740 // notifications are no longer required, crbug.com/398170.
1741 ui::SelectionBound insertion_bound;
1742 insertion_bound.set_type(ui::SelectionBound::CENTER);
1743 insertion_bound.set_visible(true);
1744 insertion_bound.SetEdge(point, point);
1745 selection_controller_->HideAndDisallowShowingAutomatically();
1746 selection_controller_->OnSelectionEditable(true);
1747 selection_controller_->OnSelectionEmpty(true);
1748 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1749 insertion_bound);
1750 selection_controller_->AllowShowingFromCurrentSelection();
1753 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1754 return cached_background_color_;
1757 void RenderWidgetHostViewAndroid::DidOverscroll(
1758 const DidOverscrollParams& params) {
1759 if (!content_view_core_ || !layer_.get() || !is_showing_)
1760 return;
1762 if (overscroll_controller_)
1763 overscroll_controller_->OnOverscrolled(params);
1766 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1767 if (content_view_core_)
1768 content_view_core_->DidStopFlinging();
1771 uint32_t RenderWidgetHostViewAndroid::GetSurfaceIdNamespace() {
1772 if (id_allocator_)
1773 return id_allocator_->id_namespace();
1774 return 0;
1777 void RenderWidgetHostViewAndroid::SetContentViewCore(
1778 ContentViewCoreImpl* content_view_core) {
1779 RemoveLayers();
1780 StopObservingRootWindow();
1782 bool resize = false;
1783 if (content_view_core != content_view_core_) {
1784 overscroll_controller_.reset();
1785 selection_controller_.reset();
1786 ReleaseLocksOnSurface();
1787 resize = true;
1790 content_view_core_ = content_view_core;
1791 content_view_core_window_android_ =
1792 content_view_core_ ? content_view_core_->GetWindowAndroid() : nullptr;
1793 DCHECK_EQ(!!content_view_core_, !!content_view_core_window_android_);
1795 BrowserAccessibilityManager* manager = NULL;
1796 if (host_)
1797 manager = host_->GetRootBrowserAccessibilityManager();
1798 if (manager) {
1799 base::android::ScopedJavaLocalRef<jobject> obj;
1800 if (content_view_core_)
1801 obj = content_view_core_->GetJavaObject();
1802 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1805 AttachLayers();
1807 if (!content_view_core_)
1808 return;
1810 if (is_showing_)
1811 StartObservingRootWindow();
1813 if (resize)
1814 WasResized();
1816 if (!selection_controller_)
1817 selection_controller_ = CreateSelectionController(this, content_view_core_);
1819 if (!overscroll_controller_ &&
1820 content_view_core_window_android_->GetCompositor()) {
1821 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1825 void RenderWidgetHostViewAndroid::RunAckCallbacks(
1826 cc::SurfaceDrawStatus status) {
1827 while (!ack_callbacks_.empty()) {
1828 ack_callbacks_.front().Run();
1829 ack_callbacks_.pop();
1833 void RenderWidgetHostViewAndroid::OnGestureEvent(
1834 const ui::GestureEventData& gesture) {
1835 blink::WebGestureEvent web_gesture =
1836 ui::CreateWebGestureEventFromGestureEventData(gesture);
1837 // TODO(jdduke): Remove this workaround after Android fixes UiAutomator to
1838 // stop providing shift meta values to synthetic MotionEvents. This prevents
1839 // unintended shift+click interpretation of all accessibility clicks.
1840 // See crbug.com/443247.
1841 if (web_gesture.type == blink::WebInputEvent::GestureTap &&
1842 web_gesture.modifiers == blink::WebInputEvent::ShiftKey) {
1843 web_gesture.modifiers = 0;
1845 SendGestureEvent(web_gesture);
1848 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1849 RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN);
1852 void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
1853 DCHECK(is_showing_);
1854 if (visible) {
1855 ShowInternal();
1856 } else {
1857 // Only hide the active frontbuffer if the Activity has been paused and
1858 // we've already hidden the host. Otherwise the root window visibility is
1859 // likely to be temporarily changing, e.g., with fullscreen video.
1860 if (host_ && host_->is_hidden()) {
1861 bool hide_frontbuffer = true;
1862 bool stop_observing_root_window = false;
1863 HideInternal(hide_frontbuffer, stop_observing_root_window);
1868 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1869 DCHECK(content_view_core_);
1870 if (!overscroll_controller_)
1871 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1874 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1875 DCHECK(content_view_core_);
1876 DCHECK(using_browser_compositor_);
1877 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1878 overscroll_controller_.reset();
1881 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1882 base::TimeDelta vsync_period) {
1883 TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync");
1884 if (!host_ || host_->is_hidden())
1885 return;
1887 if (outstanding_vsync_requests_ & FLUSH_INPUT) {
1888 outstanding_vsync_requests_ &= ~FLUSH_INPUT;
1889 host_->FlushInput();
1892 if (outstanding_vsync_requests_ & BEGIN_FRAME ||
1893 outstanding_vsync_requests_ & PERSISTENT_BEGIN_FRAME) {
1894 outstanding_vsync_requests_ &= ~BEGIN_FRAME;
1895 SendBeginFrame(frame_time, vsync_period);
1898 // This allows for SendBeginFrame and FlushInput to modify
1899 // outstanding_vsync_requests.
1900 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1901 outstanding_vsync_requests_ = 0;
1902 RequestVSyncUpdate(outstanding_vsync_requests);
1905 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1906 if (Animate(begin_frame_time))
1907 SetNeedsAnimate();
1910 void RenderWidgetHostViewAndroid::OnActivityPaused() {
1911 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityPaused");
1912 DCHECK(is_showing_);
1913 bool hide_frontbuffer = false;
1914 bool stop_observing_root_window = false;
1915 HideInternal(hide_frontbuffer, stop_observing_root_window);
1918 void RenderWidgetHostViewAndroid::OnActivityResumed() {
1919 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityResumed");
1920 DCHECK(is_showing_);
1921 ShowInternal();
1924 void RenderWidgetHostViewAndroid::OnLostResources() {
1925 ReleaseLocksOnSurface();
1926 if (layer_.get())
1927 DestroyDelegatedContent();
1928 DCHECK(ack_callbacks_.empty());
1931 // static
1932 void RenderWidgetHostViewAndroid::
1933 PrepareTextureCopyOutputResultForDelegatedReadback(
1934 const gfx::Size& dst_size_in_pixel,
1935 SkColorType color_type,
1936 const base::TimeTicks& start_time,
1937 scoped_refptr<cc::Layer> readback_layer,
1938 ReadbackRequestCallback& callback,
1939 scoped_ptr<cc::CopyOutputResult> result) {
1940 readback_layer->RemoveFromParent();
1941 PrepareTextureCopyOutputResult(
1942 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1945 // static
1946 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1947 const gfx::Size& dst_size_in_pixel,
1948 SkColorType color_type,
1949 const base::TimeTicks& start_time,
1950 ReadbackRequestCallback& callback,
1951 scoped_ptr<cc::CopyOutputResult> result) {
1952 base::ScopedClosureRunner scoped_callback_runner(
1953 base::Bind(callback, SkBitmap(), READBACK_FAILED));
1954 TRACE_EVENT0("cc",
1955 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1957 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1958 return;
1960 gfx::Size output_size_in_pixel;
1961 if (dst_size_in_pixel.IsEmpty())
1962 output_size_in_pixel = result->size();
1963 else
1964 output_size_in_pixel = dst_size_in_pixel;
1966 GLHelper* gl_helper = GetPostReadbackGLHelper();
1967 if (!gl_helper)
1968 return;
1969 if (!gl_helper->IsReadbackConfigSupported(color_type))
1970 color_type = kRGBA_8888_SkColorType;
1971 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1972 if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
1973 output_size_in_pixel.height(),
1974 color_type,
1975 kOpaque_SkAlphaType))) {
1976 scoped_callback_runner.Reset(
1977 base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
1978 return;
1982 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1983 new SkAutoLockPixels(*bitmap));
1984 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1986 cc::TextureMailbox texture_mailbox;
1987 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1988 result->TakeTexture(&texture_mailbox, &release_callback);
1989 DCHECK(texture_mailbox.IsTexture());
1990 if (!texture_mailbox.IsTexture())
1991 return;
1993 ignore_result(scoped_callback_runner.Release());
1995 gl_helper->CropScaleReadbackAndCleanMailbox(
1996 texture_mailbox.mailbox(),
1997 texture_mailbox.sync_point(),
1998 result->size(),
1999 gfx::Rect(result->size()),
2000 output_size_in_pixel,
2001 pixels,
2002 color_type,
2003 base::Bind(&CopyFromCompositingSurfaceFinished,
2004 callback,
2005 base::Passed(&release_callback),
2006 base::Passed(&bitmap),
2007 start_time,
2008 base::Passed(&bitmap_pixels_lock)),
2009 GLHelper::SCALER_QUALITY_GOOD);
2012 void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
2013 float y0,
2014 float x1,
2015 float y1) {
2016 SelectBetweenCoordinates(gfx::PointF(x0, y0), gfx::PointF(x1, y1));
2019 void RenderWidgetHostViewAndroid::OnStylusSelectUpdate(float x, float y) {
2020 MoveRangeSelectionExtent(gfx::PointF(x, y));
2023 void RenderWidgetHostViewAndroid::OnStylusSelectEnd() {
2024 if (selection_controller_)
2025 selection_controller_->AllowShowingFromCurrentSelection();
2028 void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
2029 float x,
2030 float y) {
2031 // Treat the stylus tap as a long press, activating either a word selection or
2032 // context menu depending on the targetted content.
2033 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
2034 blink::WebInputEvent::GestureLongPress,
2035 (time - base::TimeTicks()).InSecondsF(), x, y);
2036 SendGestureEvent(long_press);
2039 // static
2040 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
2041 blink::WebScreenInfo* results) {
2042 const gfx::Display& display =
2043 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
2044 results->rect = display.bounds();
2045 // TODO(husky): Remove any system controls from availableRect.
2046 results->availableRect = display.work_area();
2047 results->deviceScaleFactor = display.device_scale_factor();
2048 results->orientationAngle = display.RotationAsDegree();
2049 results->orientationType =
2050 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
2051 gfx::DeviceDisplayInfo info;
2052 results->depth = info.GetBitsPerPixel();
2053 results->depthPerComponent = info.GetBitsPerComponent();
2054 results->isMonochrome = (results->depthPerComponent == 0);
2057 } // namespace content