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