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/sys_utils.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/threading/worker_pool.h" 19 #include "cc/base/latency_info_swap_promise.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/output/compositor_frame.h" 24 #include "cc/output/compositor_frame_ack.h" 25 #include "cc/output/copy_output_request.h" 26 #include "cc/output/copy_output_result.h" 27 #include "cc/resources/single_release_callback.h" 28 #include "cc/trees/layer_tree_host.h" 29 #include "content/browser/accessibility/browser_accessibility_manager_android.h" 30 #include "content/browser/android/content_view_core_impl.h" 31 #include "content/browser/android/in_process/synchronous_compositor_impl.h" 32 #include "content/browser/android/overscroll_glow.h" 33 #include "content/browser/devtools/render_view_devtools_agent_host.h" 34 #include "content/browser/gpu/compositor_util.h" 35 #include "content/browser/gpu/gpu_data_manager_impl.h" 36 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 37 #include "content/browser/gpu/gpu_surface_tracker.h" 38 #include "content/browser/media/media_web_contents_observer.h" 39 #include "content/browser/renderer_host/compositor_impl_android.h" 40 #include "content/browser/renderer_host/dip_util.h" 41 #include "content/browser/renderer_host/image_transport_factory_android.h" 42 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" 43 #include "content/browser/renderer_host/input/web_input_event_builders_android.h" 44 #include "content/browser/renderer_host/input/web_input_event_util.h" 45 #include "content/browser/renderer_host/render_process_host_impl.h" 46 #include "content/browser/renderer_host/render_view_host_impl.h" 47 #include "content/browser/renderer_host/render_widget_host_impl.h" 48 #include "content/common/gpu/client/gl_helper.h" 49 #include "content/common/gpu/gpu_messages.h" 50 #include "content/common/input/did_overscroll_params.h" 51 #include "content/common/input_messages.h" 52 #include "content/common/view_messages.h" 53 #include "content/public/browser/browser_thread.h" 54 #include "content/public/browser/devtools_agent_host.h" 55 #include "content/public/browser/render_view_host.h" 56 #include "content/public/common/content_switches.h" 57 #include "gpu/command_buffer/client/gles2_interface.h" 58 #include "gpu/config/gpu_driver_bug_workaround_type.h" 59 #include "skia/ext/image_operations.h" 60 #include "third_party/khronos/GLES2/gl2.h" 61 #include "third_party/khronos/GLES2/gl2ext.h" 62 #include "third_party/skia/include/core/SkCanvas.h" 63 #include "ui/base/android/window_android.h" 64 #include "ui/base/android/window_android_compositor.h" 65 #include "ui/events/gesture_detection/gesture_config_helper.h" 66 #include "ui/events/gesture_detection/motion_event.h" 67 #include "ui/gfx/android/device_display_info.h" 68 #include "ui/gfx/android/java_bitmap.h" 69 #include "ui/gfx/display.h" 70 #include "ui/gfx/screen.h" 71 #include "ui/gfx/size_conversions.h" 72 73 namespace content { 74 75 namespace { 76 77 const int kUndefinedOutputSurfaceId = -1; 78 79 // Used to accomodate finite precision when comparing scaled viewport and 80 // content widths. While this value may seem large, width=device-width on an N7 81 // V1 saw errors of ~0.065 between computed window and content widths. 82 const float kMobileViewportWidthEpsilon = 0.15f; 83 84 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime"; 85 86 // Sends an acknowledgement to the renderer of a processed IME event. 87 void SendImeEventAck(RenderWidgetHostImpl* host) { 88 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID())); 89 } 90 91 void CopyFromCompositingSurfaceFinished( 92 const base::Callback<void(bool, const SkBitmap&)>& callback, 93 scoped_ptr<cc::SingleReleaseCallback> release_callback, 94 scoped_ptr<SkBitmap> bitmap, 95 const base::TimeTicks& start_time, 96 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock, 97 bool result) { 98 bitmap_pixels_lock.reset(); 99 release_callback->Run(0, false); 100 UMA_HISTOGRAM_TIMES(kAsyncReadBackString, 101 base::TimeTicks::Now() - start_time); 102 callback.Run(result, *bitmap); 103 } 104 105 ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { 106 ui::LatencyInfo latency_info; 107 // The latency number should only be added if the timestamp is valid. 108 if (event.timeStampSeconds) { 109 const int64 time_micros = static_cast<int64>( 110 event.timeStampSeconds * base::Time::kMicrosecondsPerSecond); 111 latency_info.AddLatencyNumberWithTimestamp( 112 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 113 0, 114 0, 115 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros), 116 1); 117 } 118 return latency_info; 119 } 120 121 OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters( 122 const cc::CompositorFrameMetadata& frame_metadata) { 123 const float scale_factor = 124 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor; 125 126 // Compute the size and offsets for each edge, where each effect is sized to 127 // the viewport and offset by the distance of each viewport edge to the 128 // respective content edge. 129 OverscrollGlow::DisplayParameters params; 130 params.size = gfx::ScaleSize(frame_metadata.viewport_size, scale_factor); 131 params.edge_offsets[EdgeEffect::EDGE_TOP] = 132 -frame_metadata.root_scroll_offset.y() * scale_factor; 133 params.edge_offsets[EdgeEffect::EDGE_LEFT] = 134 -frame_metadata.root_scroll_offset.x() * scale_factor; 135 params.edge_offsets[EdgeEffect::EDGE_BOTTOM] = 136 (frame_metadata.root_layer_size.height() - 137 frame_metadata.root_scroll_offset.y() - 138 frame_metadata.viewport_size.height()) * scale_factor; 139 params.edge_offsets[EdgeEffect::EDGE_RIGHT] = 140 (frame_metadata.root_layer_size.width() - 141 frame_metadata.root_scroll_offset.x() - 142 frame_metadata.viewport_size.width()) * scale_factor; 143 params.device_scale_factor = frame_metadata.device_scale_factor; 144 145 return params; 146 } 147 148 ui::GestureProvider::Config CreateGestureProviderConfig() { 149 ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig(); 150 config.disable_click_delay = 151 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableClickDelay); 152 return config; 153 } 154 155 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) { 156 return frame_metadata.min_page_scale_factor == 157 frame_metadata.max_page_scale_factor; 158 } 159 160 bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) { 161 float window_width_dip = 162 frame_metadata.page_scale_factor * frame_metadata.viewport_size.width(); 163 float content_width_css = frame_metadata.root_layer_size.width(); 164 return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon; 165 } 166 167 } // anonymous namespace 168 169 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( 170 uint32 output_id, 171 scoped_ptr<cc::CompositorFrame> output_frame) 172 : output_surface_id(output_id), frame(output_frame.Pass()) {} 173 174 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {} 175 176 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( 177 RenderWidgetHostImpl* widget_host, 178 ContentViewCoreImpl* content_view_core) 179 : host_(widget_host), 180 needs_begin_frame_(false), 181 is_showing_(!widget_host->is_hidden()), 182 content_view_core_(NULL), 183 ime_adapter_android_(this), 184 cached_background_color_(SK_ColorWHITE), 185 last_output_surface_id_(kUndefinedOutputSurfaceId), 186 weak_ptr_factory_(this), 187 overscroll_effect_enabled_(!CommandLine::ForCurrentProcess()->HasSwitch( 188 switches::kDisableOverscrollEdgeEffect)), 189 overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)), 190 gesture_provider_(CreateGestureProviderConfig(), this), 191 gesture_text_selector_(this), 192 flush_input_requested_(false), 193 accelerated_surface_route_id_(0), 194 using_synchronous_compositor_(SynchronousCompositorImpl::FromID( 195 widget_host->GetProcess()->GetID(), 196 widget_host->GetRoutingID()) != NULL), 197 frame_evictor_(new DelegatedFrameEvictor(this)), 198 locks_on_frame_count_(0), 199 observing_root_window_(false) { 200 host_->SetView(this); 201 SetContentViewCore(content_view_core); 202 ImageTransportFactoryAndroid::AddObserver(this); 203 } 204 205 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { 206 ImageTransportFactoryAndroid::RemoveObserver(this); 207 SetContentViewCore(NULL); 208 DCHECK(ack_callbacks_.empty()); 209 if (resource_collection_.get()) 210 resource_collection_->SetClient(NULL); 211 } 212 213 214 bool RenderWidgetHostViewAndroid::OnMessageReceived( 215 const IPC::Message& message) { 216 bool handled = true; 217 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message) 218 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent) 219 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor, 220 OnDidChangeBodyBackgroundColor) 221 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame, 222 OnSetNeedsBeginFrame) 223 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted, 224 OnSmartClipDataExtracted) 225 IPC_MESSAGE_UNHANDLED(handled = false) 226 IPC_END_MESSAGE_MAP() 227 return handled; 228 } 229 230 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) { 231 NOTIMPLEMENTED(); 232 } 233 234 void RenderWidgetHostViewAndroid::InitAsPopup( 235 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { 236 NOTIMPLEMENTED(); 237 } 238 239 void RenderWidgetHostViewAndroid::InitAsFullscreen( 240 RenderWidgetHostView* reference_host_view) { 241 NOTIMPLEMENTED(); 242 } 243 244 RenderWidgetHost* 245 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const { 246 return host_; 247 } 248 249 void RenderWidgetHostViewAndroid::WasShown() { 250 if (!host_ || !host_->is_hidden()) 251 return; 252 253 host_->WasShown(); 254 255 if (content_view_core_ && !using_synchronous_compositor_) { 256 content_view_core_->GetWindowAndroid()->AddObserver(this); 257 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 258 observing_root_window_ = true; 259 } 260 } 261 262 void RenderWidgetHostViewAndroid::WasHidden() { 263 RunAckCallbacks(); 264 265 if (!host_ || host_->is_hidden()) 266 return; 267 268 // Inform the renderer that we are being hidden so it can reduce its resource 269 // utilization. 270 host_->WasHidden(); 271 272 if (content_view_core_ && !using_synchronous_compositor_) { 273 content_view_core_->GetWindowAndroid()->RemoveObserver(this); 274 observing_root_window_ = false; 275 } 276 } 277 278 void RenderWidgetHostViewAndroid::WasResized() { 279 host_->WasResized(); 280 } 281 282 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) { 283 // Ignore the given size as only the Java code has the power to 284 // resize the view on Android. 285 default_size_ = size; 286 } 287 288 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) { 289 SetSize(rect.size()); 290 } 291 292 void RenderWidgetHostViewAndroid::GetScaledContentBitmap( 293 float scale, 294 SkBitmap::Config bitmap_config, 295 gfx::Rect src_subrect, 296 const base::Callback<void(bool, const SkBitmap&)>& result_callback) { 297 if (!IsSurfaceAvailableForCopy()) { 298 result_callback.Run(false, SkBitmap()); 299 return; 300 } 301 302 gfx::Size bounds = layer_->bounds(); 303 if (src_subrect.IsEmpty()) 304 src_subrect = gfx::Rect(bounds); 305 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width()); 306 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height()); 307 const gfx::Display& display = 308 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 309 float device_scale_factor = display.device_scale_factor(); 310 DCHECK_GT(device_scale_factor, 0); 311 gfx::Size dst_size( 312 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor))); 313 CopyFromCompositingSurface( 314 src_subrect, dst_size, result_callback, bitmap_config); 315 } 316 317 bool RenderWidgetHostViewAndroid::HasValidFrame() const { 318 if (!content_view_core_) 319 return false; 320 if (!layer_) 321 return false; 322 323 if (texture_size_in_layer_.IsEmpty()) 324 return false; 325 326 if (!frame_evictor_->HasFrame()) 327 return false; 328 329 return true; 330 } 331 332 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const { 333 return content_view_core_->GetViewAndroid(); 334 } 335 336 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const { 337 return reinterpret_cast<gfx::NativeViewId>( 338 const_cast<RenderWidgetHostViewAndroid*>(this)); 339 } 340 341 gfx::NativeViewAccessible 342 RenderWidgetHostViewAndroid::GetNativeViewAccessible() { 343 NOTIMPLEMENTED(); 344 return NULL; 345 } 346 347 void RenderWidgetHostViewAndroid::MovePluginWindows( 348 const std::vector<WebPluginGeometry>& moves) { 349 // We don't have plugin windows on Android. Do nothing. Note: this is called 350 // from RenderWidgetHost::OnUpdateRect which is itself invoked while 351 // processing the corresponding message from Renderer. 352 } 353 354 void RenderWidgetHostViewAndroid::Focus() { 355 host_->Focus(); 356 host_->SetInputMethodActive(true); 357 if (overscroll_effect_enabled_) 358 overscroll_effect_->Enable(); 359 } 360 361 void RenderWidgetHostViewAndroid::Blur() { 362 host_->ExecuteEditCommand("Unselect", ""); 363 host_->SetInputMethodActive(false); 364 host_->Blur(); 365 overscroll_effect_->Disable(); 366 } 367 368 bool RenderWidgetHostViewAndroid::HasFocus() const { 369 if (!content_view_core_) 370 return false; // ContentViewCore not created yet. 371 372 return content_view_core_->HasFocus(); 373 } 374 375 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const { 376 return HasValidFrame(); 377 } 378 379 void RenderWidgetHostViewAndroid::Show() { 380 if (is_showing_) 381 return; 382 383 is_showing_ = true; 384 if (layer_) 385 layer_->SetHideLayerAndSubtree(false); 386 387 frame_evictor_->SetVisible(true); 388 WasShown(); 389 } 390 391 void RenderWidgetHostViewAndroid::Hide() { 392 if (!is_showing_) 393 return; 394 395 is_showing_ = false; 396 if (layer_ && locks_on_frame_count_ == 0) 397 layer_->SetHideLayerAndSubtree(true); 398 399 frame_evictor_->SetVisible(false); 400 WasHidden(); 401 } 402 403 bool RenderWidgetHostViewAndroid::IsShowing() { 404 // ContentViewCoreImpl represents the native side of the Java 405 // ContentViewCore. It being NULL means that it is not attached 406 // to the View system yet, so we treat this RWHVA as hidden. 407 return is_showing_ && content_view_core_; 408 } 409 410 void RenderWidgetHostViewAndroid::LockCompositingSurface() { 411 DCHECK(HasValidFrame()); 412 DCHECK(host_); 413 DCHECK(frame_evictor_->HasFrame()); 414 frame_evictor_->LockFrame(); 415 locks_on_frame_count_++; 416 } 417 418 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() { 419 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0) 420 return; 421 422 DCHECK(HasValidFrame()); 423 frame_evictor_->UnlockFrame(); 424 locks_on_frame_count_--; 425 426 if (locks_on_frame_count_ == 0) { 427 if (last_frame_info_) { 428 InternalSwapCompositorFrame(last_frame_info_->output_surface_id, 429 last_frame_info_->frame.Pass()); 430 last_frame_info_.reset(); 431 } 432 433 if (!is_showing_ && layer_) 434 layer_->SetHideLayerAndSubtree(true); 435 } 436 } 437 438 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback( 439 const TextSurroundingSelectionCallback& callback) { 440 // Only one outstanding request is allowed at any given time. 441 DCHECK(!callback.is_null()); 442 text_surrounding_selection_callback_ = callback; 443 } 444 445 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse( 446 const base::string16& content, 447 size_t start_offset, 448 size_t end_offset) { 449 if (text_surrounding_selection_callback_.is_null()) 450 return; 451 text_surrounding_selection_callback_.Run(content, start_offset, end_offset); 452 text_surrounding_selection_callback_.Reset(); 453 } 454 455 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() { 456 if (!frame_evictor_->HasFrame()) { 457 DCHECK_EQ(locks_on_frame_count_, 0u); 458 return; 459 } 460 while (locks_on_frame_count_ > 0) { 461 UnlockCompositingSurface(); 462 } 463 RunAckCallbacks(); 464 } 465 466 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const { 467 if (!content_view_core_) 468 return gfx::Rect(default_size_); 469 470 return gfx::Rect(content_view_core_->GetViewSize()); 471 } 472 473 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const { 474 if (!content_view_core_) 475 return gfx::Size(); 476 477 return content_view_core_->GetPhysicalBackingSize(); 478 } 479 480 float RenderWidgetHostViewAndroid::GetOverdrawBottomHeight() const { 481 if (!content_view_core_) 482 return 0.f; 483 484 return content_view_core_->GetOverdrawBottomHeightDip(); 485 } 486 487 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) { 488 // There are no cursors on Android. 489 } 490 491 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) { 492 // Do nothing. The UI notification is handled through ContentViewClient which 493 // is TabContentsDelegate. 494 } 495 496 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() { 497 return reinterpret_cast<intptr_t>(&ime_adapter_android_); 498 } 499 500 void RenderWidgetHostViewAndroid::TextInputStateChanged( 501 const ViewHostMsg_TextInputState_Params& params) { 502 // If the change is not originated from IME (e.g. Javascript, autofill), 503 // send back the renderer an acknowledgement, regardless of how we exit from 504 // this method. 505 base::ScopedClosureRunner ack_caller; 506 if (params.is_non_ime_change) 507 ack_caller.Reset(base::Bind(&SendImeEventAck, host_)); 508 509 if (!IsShowing()) 510 return; 511 512 content_view_core_->UpdateImeAdapter( 513 GetNativeImeAdapter(), 514 static_cast<int>(params.type), 515 params.value, params.selection_start, params.selection_end, 516 params.composition_start, params.composition_end, 517 params.show_ime_if_needed, params.is_non_ime_change); 518 } 519 520 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor( 521 SkColor color) { 522 if (cached_background_color_ == color) 523 return; 524 525 cached_background_color_ = color; 526 if (content_view_core_) 527 content_view_core_->OnBackgroundColorChanged(color); 528 } 529 530 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) { 531 if (enabled == needs_begin_frame_) 532 return; 533 534 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame", 535 "enabled", enabled); 536 if (content_view_core_ && enabled) 537 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 538 539 needs_begin_frame_ = enabled; 540 } 541 542 void RenderWidgetHostViewAndroid::OnStartContentIntent( 543 const GURL& content_url) { 544 if (content_view_core_) 545 content_view_core_->StartContentIntent(content_url); 546 } 547 548 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted( 549 const base::string16& text, 550 const base::string16& html, 551 const gfx::Rect rect) { 552 if (content_view_core_) 553 content_view_core_->OnSmartClipDataExtracted(text, html, rect); 554 } 555 556 bool RenderWidgetHostViewAndroid::OnTouchEvent( 557 const ui::MotionEvent& event) { 558 if (!host_) 559 return false; 560 561 if (!gesture_provider_.OnTouchEvent(event)) 562 return false; 563 564 if (gesture_text_selector_.OnTouchEvent(event)) { 565 gesture_provider_.OnTouchEventAck(false); 566 return true; 567 } 568 569 // Short-circuit touch forwarding if no touch handlers exist. 570 if (!host_->ShouldForwardTouchEvent()) { 571 const bool event_consumed = false; 572 gesture_provider_.OnTouchEventAck(event_consumed); 573 return true; 574 } 575 576 SendTouchEvent(CreateWebTouchEventFromMotionEvent(event)); 577 return true; 578 } 579 580 void RenderWidgetHostViewAndroid::ResetGestureDetection() { 581 const ui::MotionEvent* current_down_event = 582 gesture_provider_.GetCurrentDownEvent(); 583 if (!current_down_event) 584 return; 585 586 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel(); 587 DCHECK(cancel_event); 588 OnTouchEvent(*cancel_event); 589 } 590 591 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) { 592 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled); 593 } 594 595 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled( 596 bool enabled) { 597 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled); 598 } 599 600 void RenderWidgetHostViewAndroid::ImeCancelComposition() { 601 ime_adapter_android_.CancelComposition(); 602 } 603 604 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) { 605 ime_adapter_android_.FocusedNodeChanged(is_editable_node); 606 } 607 608 void RenderWidgetHostViewAndroid::RenderProcessGone( 609 base::TerminationStatus status, int error_code) { 610 Destroy(); 611 } 612 613 void RenderWidgetHostViewAndroid::Destroy() { 614 RemoveLayers(); 615 SetContentViewCore(NULL); 616 617 // The RenderWidgetHost's destruction led here, so don't call it. 618 host_ = NULL; 619 620 delete this; 621 } 622 623 void RenderWidgetHostViewAndroid::SetTooltipText( 624 const base::string16& tooltip_text) { 625 // Tooltips don't makes sense on Android. 626 } 627 628 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text, 629 size_t offset, 630 const gfx::Range& range) { 631 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); 632 633 if (text.empty() || range.is_empty() || !content_view_core_) 634 return; 635 size_t pos = range.GetMin() - offset; 636 size_t n = range.length(); 637 638 DCHECK(pos + n <= text.length()) << "The text can not fully cover range."; 639 if (pos >= text.length()) { 640 NOTREACHED() << "The text can not cover range."; 641 return; 642 } 643 644 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n)); 645 646 content_view_core_->OnSelectionChanged(utf8_selection); 647 } 648 649 void RenderWidgetHostViewAndroid::SelectionBoundsChanged( 650 const ViewHostMsg_SelectionBounds_Params& params) { 651 if (content_view_core_) { 652 content_view_core_->OnSelectionBoundsChanged(params); 653 } 654 } 655 656 void RenderWidgetHostViewAndroid::ScrollOffsetChanged() { 657 } 658 659 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) { 660 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque); 661 host_->SetBackgroundOpaque(opaque); 662 } 663 664 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( 665 const gfx::Rect& src_subrect, 666 const gfx::Size& dst_size, 667 const base::Callback<void(bool, const SkBitmap&)>& callback, 668 const SkBitmap::Config bitmap_config) { 669 if (!IsReadbackConfigSupported(bitmap_config)) { 670 callback.Run(false, SkBitmap()); 671 return; 672 } 673 base::TimeTicks start_time = base::TimeTicks::Now(); 674 if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) { 675 callback.Run(false, SkBitmap()); 676 return; 677 } 678 const gfx::Display& display = 679 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 680 float device_scale_factor = display.device_scale_factor(); 681 gfx::Size dst_size_in_pixel = 682 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size(); 683 gfx::Rect src_subrect_in_pixel = 684 ConvertRectToPixel(device_scale_factor, src_subrect); 685 686 if (using_synchronous_compositor_) { 687 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback, 688 bitmap_config); 689 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous", 690 base::TimeTicks::Now() - start_time); 691 return; 692 } 693 694 scoped_ptr<cc::CopyOutputRequest> request; 695 scoped_refptr<cc::Layer> readback_layer; 696 DCHECK(content_view_core_); 697 DCHECK(content_view_core_->GetWindowAndroid()); 698 ui::WindowAndroidCompositor* compositor = 699 content_view_core_->GetWindowAndroid()->GetCompositor(); 700 DCHECK(compositor); 701 DCHECK(frame_provider_); 702 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer = 703 cc::DelegatedRendererLayer::Create(frame_provider_); 704 delegated_layer->SetBounds(content_size_in_layer_); 705 delegated_layer->SetHideLayerAndSubtree(true); 706 delegated_layer->SetIsDrawable(true); 707 delegated_layer->SetContentsOpaque(true); 708 compositor->AttachLayerForReadback(delegated_layer); 709 710 readback_layer = delegated_layer; 711 request = cc::CopyOutputRequest::CreateRequest( 712 base::Bind(&RenderWidgetHostViewAndroid:: 713 PrepareTextureCopyOutputResultForDelegatedReadback, 714 dst_size_in_pixel, 715 bitmap_config, 716 start_time, 717 readback_layer, 718 callback)); 719 request->set_area(src_subrect_in_pixel); 720 readback_layer->RequestCopyOfOutput(request.Pass()); 721 } 722 723 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( 724 const gfx::Rect& src_subrect, 725 const scoped_refptr<media::VideoFrame>& target, 726 const base::Callback<void(bool)>& callback) { 727 NOTIMPLEMENTED(); 728 callback.Run(false); 729 } 730 731 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const { 732 return false; 733 } 734 735 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup( 736 const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) { 737 if (!content_view_core_) 738 return; 739 740 content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap); 741 } 742 743 scoped_ptr<SyntheticGestureTarget> 744 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() { 745 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid( 746 host_, content_view_core_->CreateTouchEventSynthesizer())); 747 } 748 749 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck( 750 uint32 output_surface_id) { 751 DCHECK(host_); 752 cc::CompositorFrameAck ack; 753 if (resource_collection_.get()) 754 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 755 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(), 756 output_surface_id, 757 host_->GetProcess()->GetID(), 758 ack); 759 } 760 761 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources( 762 uint32 output_surface_id) { 763 DCHECK(resource_collection_); 764 765 cc::CompositorFrameAck ack; 766 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 767 DCHECK(!ack.resources.empty()); 768 769 RenderWidgetHostImpl::SendReclaimCompositorResources( 770 host_->GetRoutingID(), 771 output_surface_id, 772 host_->GetProcess()->GetID(), 773 ack); 774 } 775 776 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() { 777 if (ack_callbacks_.size()) 778 return; 779 SendReturnedDelegatedResources(last_output_surface_id_); 780 } 781 782 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() { 783 RemoveLayers(); 784 frame_provider_ = NULL; 785 layer_ = NULL; 786 } 787 788 void RenderWidgetHostViewAndroid::SwapDelegatedFrame( 789 uint32 output_surface_id, 790 scoped_ptr<cc::DelegatedFrameData> frame_data) { 791 bool has_content = !texture_size_in_layer_.IsEmpty(); 792 793 if (output_surface_id != last_output_surface_id_) { 794 // Drop the cc::DelegatedFrameResourceCollection so that we will not return 795 // any resources from the old output surface with the new output surface id. 796 if (resource_collection_.get()) { 797 resource_collection_->SetClient(NULL); 798 if (resource_collection_->LoseAllResources()) 799 SendReturnedDelegatedResources(last_output_surface_id_); 800 resource_collection_ = NULL; 801 } 802 DestroyDelegatedContent(); 803 804 last_output_surface_id_ = output_surface_id; 805 } 806 807 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the 808 // renderer frame, assuming that the browser compositor will scale 809 // it back up to device scale. But on Android we put our browser layers in 810 // physical pixels and set our browser CC device_scale_factor to 1, so this 811 // suppresses the transform. This line may need to be removed when fixing 812 // http://crbug.com/384134 or http://crbug.com/310763 813 frame_data->device_scale_factor = 1.0f; 814 815 if (!has_content) { 816 DestroyDelegatedContent(); 817 } else { 818 if (!resource_collection_.get()) { 819 resource_collection_ = new cc::DelegatedFrameResourceCollection; 820 resource_collection_->SetClient(this); 821 } 822 if (!frame_provider_ || 823 texture_size_in_layer_ != frame_provider_->frame_size()) { 824 RemoveLayers(); 825 frame_provider_ = new cc::DelegatedFrameProvider( 826 resource_collection_.get(), frame_data.Pass()); 827 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_); 828 AttachLayers(); 829 } else { 830 frame_provider_->SetFrameData(frame_data.Pass()); 831 } 832 } 833 834 if (layer_.get()) { 835 layer_->SetIsDrawable(true); 836 layer_->SetContentsOpaque(true); 837 layer_->SetBounds(content_size_in_layer_); 838 layer_->SetNeedsDisplay(); 839 } 840 841 base::Closure ack_callback = 842 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck, 843 weak_ptr_factory_.GetWeakPtr(), 844 output_surface_id); 845 846 ack_callbacks_.push(ack_callback); 847 if (host_->is_hidden()) 848 RunAckCallbacks(); 849 } 850 851 void RenderWidgetHostViewAndroid::ComputeContentsSize( 852 const cc::CompositorFrameMetadata& frame_metadata) { 853 // Calculate the content size. This should be 0 if the texture_size is 0. 854 gfx::Vector2dF offset; 855 if (texture_size_in_layer_.GetArea() > 0) 856 offset = frame_metadata.location_bar_content_translation; 857 offset.set_y(offset.y() + frame_metadata.overdraw_bottom_height); 858 offset.Scale(frame_metadata.device_scale_factor); 859 content_size_in_layer_ = 860 gfx::Size(texture_size_in_layer_.width() - offset.x(), 861 texture_size_in_layer_.height() - offset.y()); 862 863 overscroll_effect_->UpdateDisplayParameters( 864 CreateOverscrollDisplayParameters(frame_metadata)); 865 } 866 867 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame( 868 uint32 output_surface_id, 869 scoped_ptr<cc::CompositorFrame> frame) { 870 if (!frame->delegated_frame_data) { 871 LOG(ERROR) << "Non-delegated renderer path no longer supported"; 872 return; 873 } 874 875 if (locks_on_frame_count_ > 0) { 876 DCHECK(HasValidFrame()); 877 RetainFrame(output_surface_id, frame.Pass()); 878 return; 879 } 880 881 if (layer_ && layer_->layer_tree_host()) { 882 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) { 883 scoped_ptr<cc::SwapPromise> swap_promise( 884 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i])); 885 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass()); 886 } 887 } 888 889 DCHECK(!frame->delegated_frame_data->render_pass_list.empty()); 890 891 cc::RenderPass* root_pass = 892 frame->delegated_frame_data->render_pass_list.back(); 893 texture_size_in_layer_ = root_pass->output_rect.size(); 894 ComputeContentsSize(frame->metadata); 895 896 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass()); 897 frame_evictor_->SwappedFrame(!host_->is_hidden()); 898 899 OnFrameMetadataUpdated(frame->metadata); 900 } 901 902 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( 903 uint32 output_surface_id, 904 scoped_ptr<cc::CompositorFrame> frame) { 905 InternalSwapCompositorFrame(output_surface_id, frame.Pass()); 906 } 907 908 void RenderWidgetHostViewAndroid::RetainFrame( 909 uint32 output_surface_id, 910 scoped_ptr<cc::CompositorFrame> frame) { 911 DCHECK(locks_on_frame_count_); 912 913 // Store the incoming frame so that it can be swapped when all the locks have 914 // been released. If there is already a stored frame, then replace and skip 915 // the previous one but make sure we still eventually send the ACK. Holding 916 // the ACK also blocks the renderer when its max_frames_pending is reached. 917 if (last_frame_info_) { 918 base::Closure ack_callback = 919 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck, 920 weak_ptr_factory_.GetWeakPtr(), 921 last_frame_info_->output_surface_id); 922 923 ack_callbacks_.push(ack_callback); 924 } 925 926 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass())); 927 } 928 929 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata( 930 const cc::CompositorFrameMetadata& frame_metadata) { 931 // This is a subset of OnSwapCompositorFrame() used in the synchronous 932 // compositor flow. 933 OnFrameMetadataUpdated(frame_metadata); 934 ComputeContentsSize(frame_metadata); 935 936 // DevTools ScreenCast support for Android WebView. 937 if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) { 938 scoped_refptr<DevToolsAgentHost> dtah = 939 DevToolsAgentHost::GetOrCreateFor( 940 RenderViewHost::From(GetRenderWidgetHost())); 941 // Unblock the compositor. 942 BrowserThread::PostTask( 943 BrowserThread::UI, FROM_HERE, 944 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame, 945 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()), 946 frame_metadata)); 947 } 948 } 949 950 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) { 951 if (layer_) 952 layer_->SetContentsOpaque(!enabled); 953 } 954 955 void RenderWidgetHostViewAndroid::SynchronousCopyContents( 956 const gfx::Rect& src_subrect_in_pixel, 957 const gfx::Size& dst_size_in_pixel, 958 const base::Callback<void(bool, const SkBitmap&)>& callback, 959 const SkBitmap::Config config) { 960 SynchronousCompositor* compositor = 961 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), 962 host_->GetRoutingID()); 963 if (!compositor) { 964 callback.Run(false, SkBitmap()); 965 return; 966 } 967 968 SkBitmap bitmap; 969 bitmap.setConfig(config, 970 dst_size_in_pixel.width(), 971 dst_size_in_pixel.height()); 972 bitmap.allocPixels(); 973 SkCanvas canvas(bitmap); 974 canvas.scale( 975 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(), 976 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height()); 977 compositor->DemandDrawSw(&canvas); 978 callback.Run(true, bitmap); 979 } 980 981 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated( 982 const cc::CompositorFrameMetadata& frame_metadata) { 983 984 // Disable double tap zoom for pages that have a width=device-width or 985 // narrower viewport (indicating that this is a mobile-optimized or responsive 986 // web design, so text will be legible without zooming). Also disable 987 // double tap and pinch for pages that prevent zooming in or out. 988 bool has_mobile_viewport = HasMobileViewport(frame_metadata); 989 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata); 990 gesture_provider_.SetDoubleTapSupportForPageEnabled( 991 !has_fixed_page_scale && !has_mobile_viewport); 992 993 if (!content_view_core_) 994 return; 995 // All offsets and sizes are in CSS pixels. 996 content_view_core_->UpdateFrameInfo( 997 frame_metadata.root_scroll_offset, 998 frame_metadata.page_scale_factor, 999 gfx::Vector2dF(frame_metadata.min_page_scale_factor, 1000 frame_metadata.max_page_scale_factor), 1001 frame_metadata.root_layer_size, 1002 frame_metadata.viewport_size, 1003 frame_metadata.location_bar_offset, 1004 frame_metadata.location_bar_content_translation, 1005 frame_metadata.overdraw_bottom_height); 1006 #if defined(VIDEO_HOLE) 1007 if (host_ && host_->IsRenderView()) { 1008 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>( 1009 RenderViewHost::From(host_)); 1010 rvhi->media_web_contents_observer()->OnFrameInfoUpdated(); 1011 } 1012 #endif // defined(VIDEO_HOLE) 1013 } 1014 1015 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id, 1016 int route_id) { 1017 accelerated_surface_route_id_ = route_id; 1018 } 1019 1020 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped( 1021 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 1022 int gpu_host_id) { 1023 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer"; 1024 } 1025 1026 void RenderWidgetHostViewAndroid::AttachLayers() { 1027 if (!content_view_core_) 1028 return; 1029 if (!layer_.get()) 1030 return; 1031 1032 content_view_core_->AttachLayer(layer_); 1033 if (overscroll_effect_enabled_) 1034 overscroll_effect_->Enable(); 1035 layer_->SetHideLayerAndSubtree(!is_showing_); 1036 } 1037 1038 void RenderWidgetHostViewAndroid::RemoveLayers() { 1039 if (!content_view_core_) 1040 return; 1041 if (!layer_.get()) 1042 return; 1043 1044 content_view_core_->RemoveLayer(layer_); 1045 overscroll_effect_->Disable(); 1046 } 1047 1048 void RenderWidgetHostViewAndroid::SetNeedsAnimate() { 1049 content_view_core_->GetWindowAndroid()->SetNeedsAnimate(); 1050 } 1051 1052 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) { 1053 return overscroll_effect_->Animate(frame_time); 1054 } 1055 1056 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer( 1057 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, 1058 int gpu_host_id) { 1059 NOTREACHED(); 1060 } 1061 1062 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() { 1063 NOTREACHED(); 1064 } 1065 1066 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() { 1067 NOTREACHED(); 1068 } 1069 1070 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() { 1071 if (layer_.get()) 1072 DestroyDelegatedContent(); 1073 frame_evictor_->DiscardedFrame(); 1074 } 1075 1076 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface( 1077 const gfx::Size& desired_size) { 1078 NOTREACHED(); 1079 return false; 1080 } 1081 1082 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) { 1083 // ScreenInfo isn't tied to the widget on Android. Always return the default. 1084 RenderWidgetHostViewBase::GetDefaultScreenInfo(result); 1085 } 1086 1087 // TODO(jrg): Find out the implications and answer correctly here, 1088 // as we are returning the WebView and not root window bounds. 1089 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() { 1090 return GetViewBounds(); 1091 } 1092 1093 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() { 1094 gfx::GLSurfaceHandle handle = 1095 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT); 1096 if (CompositorImpl::IsInitialized()) { 1097 handle.parent_client_id = 1098 ImageTransportFactoryAndroid::GetInstance()->GetChannelID(); 1099 } 1100 return handle; 1101 } 1102 1103 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent( 1104 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { 1105 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; 1106 gesture_provider_.OnTouchEventAck(event_consumed); 1107 } 1108 1109 void RenderWidgetHostViewAndroid::GestureEventAck( 1110 const blink::WebGestureEvent& event, 1111 InputEventAckState ack_result) { 1112 if (content_view_core_) 1113 content_view_core_->OnGestureEventAck(event, ack_result); 1114 } 1115 1116 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent( 1117 const blink::WebInputEvent& input_event) { 1118 if (content_view_core_ && 1119 content_view_core_->FilterInputEvent(input_event)) 1120 return INPUT_EVENT_ACK_STATE_CONSUMED; 1121 1122 if (!host_) 1123 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 1124 1125 if (input_event.type == blink::WebInputEvent::GestureTapDown || 1126 input_event.type == blink::WebInputEvent::TouchStart) { 1127 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance(); 1128 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); 1129 if (shim && gpu_data && accelerated_surface_route_id_ && 1130 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING)) 1131 shim->Send( 1132 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_)); 1133 } 1134 1135 SynchronousCompositorImpl* compositor = 1136 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), 1137 host_->GetRoutingID()); 1138 if (compositor) 1139 return compositor->HandleInputEvent(input_event); 1140 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 1141 } 1142 1143 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() { 1144 if (flush_input_requested_ || !content_view_core_) 1145 return; 1146 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput"); 1147 flush_input_requested_ = true; 1148 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 1149 } 1150 1151 void RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManagerIfNeeded() { 1152 if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete) 1153 return; 1154 1155 if (!GetBrowserAccessibilityManager()) { 1156 base::android::ScopedJavaLocalRef<jobject> obj; 1157 if (content_view_core_) 1158 obj = content_view_core_->GetJavaObject(); 1159 SetBrowserAccessibilityManager( 1160 new BrowserAccessibilityManagerAndroid( 1161 obj, 1162 BrowserAccessibilityManagerAndroid::GetEmptyDocument(), 1163 host_)); 1164 } 1165 } 1166 1167 bool RenderWidgetHostViewAndroid::LockMouse() { 1168 NOTIMPLEMENTED(); 1169 return false; 1170 } 1171 1172 void RenderWidgetHostViewAndroid::UnlockMouse() { 1173 NOTIMPLEMENTED(); 1174 } 1175 1176 // Methods called from the host to the render 1177 1178 void RenderWidgetHostViewAndroid::SendKeyEvent( 1179 const NativeWebKeyboardEvent& event) { 1180 if (host_) 1181 host_->ForwardKeyboardEvent(event); 1182 } 1183 1184 void RenderWidgetHostViewAndroid::SendTouchEvent( 1185 const blink::WebTouchEvent& event) { 1186 if (host_) 1187 host_->ForwardTouchEventWithLatencyInfo(event, CreateLatencyInfo(event)); 1188 1189 // Send a proactive BeginFrame on the next vsync to reduce latency. 1190 // This is good enough as long as the first touch event has Begin semantics 1191 // and the actual scroll happens on the next vsync. 1192 // TODO: Is this actually still needed? 1193 if (content_view_core_ && observing_root_window_) { 1194 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 1195 } 1196 } 1197 1198 void RenderWidgetHostViewAndroid::SendMouseEvent( 1199 const blink::WebMouseEvent& event) { 1200 if (host_) 1201 host_->ForwardMouseEvent(event); 1202 } 1203 1204 void RenderWidgetHostViewAndroid::SendMouseWheelEvent( 1205 const blink::WebMouseWheelEvent& event) { 1206 if (host_) 1207 host_->ForwardWheelEvent(event); 1208 } 1209 1210 void RenderWidgetHostViewAndroid::SendGestureEvent( 1211 const blink::WebGestureEvent& event) { 1212 // Sending a gesture that may trigger overscroll should resume the effect. 1213 if (overscroll_effect_enabled_) 1214 overscroll_effect_->Enable(); 1215 1216 if (host_) 1217 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event)); 1218 } 1219 1220 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) { 1221 if (host_) 1222 host_->MoveCaret(point); 1223 } 1224 1225 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const { 1226 return cached_background_color_; 1227 } 1228 1229 void RenderWidgetHostViewAndroid::DidOverscroll( 1230 const DidOverscrollParams& params) { 1231 if (!content_view_core_ || !layer_ || !is_showing_) 1232 return; 1233 1234 const float device_scale_factor = content_view_core_->GetDpiScale(); 1235 if (overscroll_effect_->OnOverscrolled( 1236 content_view_core_->GetLayer(), 1237 base::TimeTicks::Now(), 1238 gfx::ScaleVector2d(params.accumulated_overscroll, 1239 device_scale_factor), 1240 gfx::ScaleVector2d(params.latest_overscroll_delta, 1241 device_scale_factor), 1242 gfx::ScaleVector2d(params.current_fling_velocity, 1243 device_scale_factor))) { 1244 SetNeedsAnimate(); 1245 } 1246 } 1247 1248 void RenderWidgetHostViewAndroid::DidStopFlinging() { 1249 if (content_view_core_) 1250 content_view_core_->DidStopFlinging(); 1251 } 1252 1253 void RenderWidgetHostViewAndroid::SetContentViewCore( 1254 ContentViewCoreImpl* content_view_core) { 1255 RemoveLayers(); 1256 if (observing_root_window_ && content_view_core_) { 1257 content_view_core_->GetWindowAndroid()->RemoveObserver(this); 1258 observing_root_window_ = false; 1259 } 1260 1261 bool resize = false; 1262 if (content_view_core != content_view_core_) { 1263 ReleaseLocksOnSurface(); 1264 resize = true; 1265 } 1266 1267 content_view_core_ = content_view_core; 1268 1269 if (GetBrowserAccessibilityManager()) { 1270 base::android::ScopedJavaLocalRef<jobject> obj; 1271 if (content_view_core_) 1272 obj = content_view_core_->GetJavaObject(); 1273 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()-> 1274 SetContentViewCore(obj); 1275 } 1276 1277 AttachLayers(); 1278 if (content_view_core_ && !using_synchronous_compositor_) { 1279 content_view_core_->GetWindowAndroid()->AddObserver(this); 1280 observing_root_window_ = true; 1281 if (needs_begin_frame_) 1282 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 1283 } 1284 1285 if (resize && content_view_core_) 1286 WasResized(); 1287 } 1288 1289 void RenderWidgetHostViewAndroid::RunAckCallbacks() { 1290 while (!ack_callbacks_.empty()) { 1291 ack_callbacks_.front().Run(); 1292 ack_callbacks_.pop(); 1293 } 1294 } 1295 1296 void RenderWidgetHostViewAndroid::OnGestureEvent( 1297 const ui::GestureEventData& gesture) { 1298 if (gesture_text_selector_.OnGestureEvent(gesture)) 1299 return; 1300 1301 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture)); 1302 } 1303 1304 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() { 1305 RunAckCallbacks(); 1306 } 1307 1308 void RenderWidgetHostViewAndroid::OnDetachCompositor() { 1309 DCHECK(content_view_core_); 1310 DCHECK(!using_synchronous_compositor_); 1311 RunAckCallbacks(); 1312 } 1313 1314 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, 1315 base::TimeDelta vsync_period) { 1316 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync"); 1317 if (!host_) 1318 return; 1319 1320 if (flush_input_requested_) { 1321 flush_input_requested_ = false; 1322 host_->FlushInput(); 1323 } 1324 1325 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame"); 1326 base::TimeTicks display_time = frame_time + vsync_period; 1327 1328 // TODO(brianderson): Use adaptive draw-time estimation. 1329 base::TimeDelta estimated_browser_composite_time = 1330 base::TimeDelta::FromMicroseconds( 1331 (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60)); 1332 1333 base::TimeTicks deadline = display_time - estimated_browser_composite_time; 1334 1335 host_->Send(new ViewMsg_BeginFrame( 1336 host_->GetRoutingID(), 1337 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period))); 1338 1339 if (needs_begin_frame_) 1340 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 1341 } 1342 1343 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) { 1344 if (Animate(begin_frame_time)) 1345 SetNeedsAnimate(); 1346 } 1347 1348 void RenderWidgetHostViewAndroid::OnLostResources() { 1349 ReleaseLocksOnSurface(); 1350 if (layer_.get()) 1351 DestroyDelegatedContent(); 1352 DCHECK(ack_callbacks_.empty()); 1353 } 1354 1355 // static 1356 void 1357 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback( 1358 const gfx::Size& dst_size_in_pixel, 1359 const SkBitmap::Config config, 1360 const base::TimeTicks& start_time, 1361 scoped_refptr<cc::Layer> readback_layer, 1362 const base::Callback<void(bool, const SkBitmap&)>& callback, 1363 scoped_ptr<cc::CopyOutputResult> result) { 1364 readback_layer->RemoveFromParent(); 1365 PrepareTextureCopyOutputResult( 1366 dst_size_in_pixel, config, start_time, callback, result.Pass()); 1367 } 1368 1369 // static 1370 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult( 1371 const gfx::Size& dst_size_in_pixel, 1372 const SkBitmap::Config bitmap_config, 1373 const base::TimeTicks& start_time, 1374 const base::Callback<void(bool, const SkBitmap&)>& callback, 1375 scoped_ptr<cc::CopyOutputResult> result) { 1376 base::ScopedClosureRunner scoped_callback_runner( 1377 base::Bind(callback, false, SkBitmap())); 1378 1379 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty()) 1380 return; 1381 1382 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 1383 bitmap->setConfig(bitmap_config, 1384 dst_size_in_pixel.width(), 1385 dst_size_in_pixel.height(), 1386 0, kOpaque_SkAlphaType); 1387 if (!bitmap->allocPixels()) 1388 return; 1389 1390 ImageTransportFactoryAndroid* factory = 1391 ImageTransportFactoryAndroid::GetInstance(); 1392 GLHelper* gl_helper = factory->GetGLHelper(); 1393 1394 if (!gl_helper) 1395 return; 1396 1397 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock( 1398 new SkAutoLockPixels(*bitmap)); 1399 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); 1400 1401 cc::TextureMailbox texture_mailbox; 1402 scoped_ptr<cc::SingleReleaseCallback> release_callback; 1403 result->TakeTexture(&texture_mailbox, &release_callback); 1404 DCHECK(texture_mailbox.IsTexture()); 1405 if (!texture_mailbox.IsTexture()) 1406 return; 1407 1408 ignore_result(scoped_callback_runner.Release()); 1409 1410 gl_helper->CropScaleReadbackAndCleanMailbox( 1411 texture_mailbox.mailbox(), 1412 texture_mailbox.sync_point(), 1413 result->size(), 1414 gfx::Rect(result->size()), 1415 dst_size_in_pixel, 1416 pixels, 1417 bitmap_config, 1418 base::Bind(&CopyFromCompositingSurfaceFinished, 1419 callback, 1420 base::Passed(&release_callback), 1421 base::Passed(&bitmap), 1422 start_time, 1423 base::Passed(&bitmap_pixels_lock)), 1424 GLHelper::SCALER_QUALITY_GOOD); 1425 } 1426 1427 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported( 1428 SkBitmap::Config bitmap_config) { 1429 ImageTransportFactoryAndroid* factory = 1430 ImageTransportFactoryAndroid::GetInstance(); 1431 GLHelper* gl_helper = factory->GetGLHelper(); 1432 if (!gl_helper) 1433 return false; 1434 return gl_helper->IsReadbackConfigSupported(bitmap_config); 1435 } 1436 1437 SkBitmap::Config RenderWidgetHostViewAndroid::PreferredReadbackFormat() { 1438 // Define the criteria here. If say the 16 texture readback is 1439 // supported we should go with that (this degrades quality) 1440 // or stick back to the default format. 1441 if (base::android::SysUtils::IsLowEndDevice()) { 1442 if (IsReadbackConfigSupported(SkBitmap::kRGB_565_Config)) 1443 return SkBitmap::kRGB_565_Config; 1444 } 1445 return SkBitmap::kARGB_8888_Config; 1446 } 1447 1448 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() { 1449 if (content_view_core_) 1450 content_view_core_->ShowSelectionHandlesAutomatically(); 1451 } 1452 1453 void RenderWidgetHostViewAndroid::SelectRange( 1454 float x1, float y1, float x2, float y2) { 1455 if (content_view_core_) 1456 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())-> 1457 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2)); 1458 } 1459 1460 void RenderWidgetHostViewAndroid::Unselect() { 1461 if (content_view_core_) 1462 content_view_core_->GetWebContents()->Unselect(); 1463 } 1464 1465 void RenderWidgetHostViewAndroid::LongPress( 1466 base::TimeTicks time, float x, float y) { 1467 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build( 1468 blink::WebInputEvent::GestureLongPress, 1469 (time - base::TimeTicks()).InSecondsF(), x, y); 1470 SendGestureEvent(long_press); 1471 } 1472 1473 // static 1474 void RenderWidgetHostViewBase::GetDefaultScreenInfo( 1475 blink::WebScreenInfo* results) { 1476 const gfx::Display& display = 1477 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 1478 results->rect = display.bounds(); 1479 // TODO(husky): Remove any system controls from availableRect. 1480 results->availableRect = display.work_area(); 1481 results->deviceScaleFactor = display.device_scale_factor(); 1482 results->orientationAngle = display.RotationAsDegree(); 1483 gfx::DeviceDisplayInfo info; 1484 results->depth = info.GetBitsPerPixel(); 1485 results->depthPerComponent = info.GetBitsPerComponent(); 1486 results->isMonochrome = (results->depthPerComponent == 0); 1487 } 1488 1489 } // namespace content 1490