render_widget_host_view_guest.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
1// Copyright 2014 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 "base/bind_helpers.h" 6#include "base/command_line.h" 7#include "base/logging.h" 8#include "base/message_loop/message_loop.h" 9#include "content/browser/browser_plugin/browser_plugin_guest.h" 10#include "content/browser/frame_host/render_widget_host_view_guest.h" 11#include "content/browser/renderer_host/render_view_host_impl.h" 12#include "content/common/browser_plugin/browser_plugin_messages.h" 13#include "content/common/frame_messages.h" 14#include "content/common/gpu/gpu_messages.h" 15#include "content/common/host_shared_bitmap_manager.h" 16#include "content/common/view_messages.h" 17#include "content/common/webplugin_geometry.h" 18#include "content/public/common/content_switches.h" 19#include "skia/ext/platform_canvas.h" 20#include "third_party/WebKit/public/platform/WebScreenInfo.h" 21 22#if defined(OS_MACOSX) 23#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h" 24#endif 25 26#if defined(USE_AURA) 27#include "content/browser/renderer_host/ui_events_helper.h" 28#endif 29 30namespace content { 31 32namespace { 33 34#if defined(USE_AURA) 35blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) { 36 blink::WebGestureEvent gesture_event; 37 gesture_event.timeStampSeconds = time_stamp; 38 gesture_event.type = blink::WebGestureEvent::GestureFlingCancel; 39 gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen; 40 return gesture_event; 41} 42#endif // defined(USE_AURA) 43 44} // namespace 45 46RenderWidgetHostViewGuest::RenderWidgetHostViewGuest( 47 RenderWidgetHost* widget_host, 48 BrowserPluginGuest* guest, 49 RenderWidgetHostView* platform_view) 50 : RenderWidgetHostViewChildFrame(widget_host), 51 // |guest| is NULL during test. 52 guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()), 53 platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) { 54#if defined(USE_AURA) 55 gesture_recognizer_.reset(ui::GestureRecognizer::Create()); 56 gesture_recognizer_->AddGestureEventHelper(this); 57#endif // defined(USE_AURA) 58} 59 60RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() { 61#if defined(USE_AURA) 62 gesture_recognizer_->RemoveGestureEventHelper(this); 63#endif // defined(USE_AURA) 64} 65 66void RenderWidgetHostViewGuest::WasShown() { 67 // If the WebContents associated with us showed an interstitial page in the 68 // beginning, the teardown path might call WasShown() while |host_| is in 69 // the process of destruction. Avoid calling WasShown below in this case. 70 // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the 71 // first place: http://crbug.com/273089. 72 // 73 // |guest_| is NULL during test. 74 if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden()) 75 return; 76 host_->WasShown(); 77} 78 79void RenderWidgetHostViewGuest::WasHidden() { 80 // |guest_| is NULL during test. 81 if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden()) 82 return; 83 host_->WasHidden(); 84} 85 86void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) { 87 size_ = size; 88 host_->WasResized(); 89} 90 91void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) { 92 SetSize(rect.size()); 93} 94 95#if defined(USE_AURA) 96void RenderWidgetHostViewGuest::ProcessAckedTouchEvent( 97 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { 98 // TODO(fsamuel): Currently we will only take this codepath if the guest has 99 // requested touch events. A better solution is to always forward touchpresses 100 // to the embedder process to target a BrowserPlugin, and then route all 101 // subsequent touch points of that touchdown to the appropriate guest until 102 // that touch point is released. 103 ScopedVector<ui::TouchEvent> events; 104 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES)) 105 return; 106 107 ui::EventResult result = (ack_result == 108 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; 109 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), 110 end = events.end(); iter != end; ++iter) { 111 scoped_ptr<ui::GestureRecognizer::Gestures> gestures; 112 gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( 113 *(*iter), result, this)); 114 ProcessGestures(gestures.get()); 115 } 116} 117#endif 118 119gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const { 120 if (!guest_) 121 return gfx::Rect(); 122 123 RenderWidgetHostViewPort* rwhv = static_cast<RenderWidgetHostViewPort*>( 124 guest_->GetEmbedderRenderWidgetHostView()); 125 gfx::Rect embedder_bounds; 126 if (rwhv) 127 embedder_bounds = rwhv->GetViewBounds(); 128 gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds); 129 shifted_rect.set_width(size_.width()); 130 shifted_rect.set_height(size_.height()); 131 return shifted_rect; 132} 133 134void RenderWidgetHostViewGuest::RenderProcessGone( 135 base::TerminationStatus status, 136 int error_code) { 137 platform_view_->RenderProcessGone(status, error_code); 138 // Destroy the guest view instance only, so we don't end up calling 139 // platform_view_->Destroy(). 140 DestroyGuestView(); 141} 142 143void RenderWidgetHostViewGuest::Destroy() { 144 // The RenderWidgetHost's destruction led here, so don't call it. 145 DestroyGuestView(); 146 147 platform_view_->Destroy(); 148} 149 150gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const { 151 return RenderWidgetHostViewBase::GetPhysicalBackingSize(); 152} 153 154base::string16 RenderWidgetHostViewGuest::GetSelectedText() const { 155 return platform_view_->GetSelectedText(); 156} 157 158void RenderWidgetHostViewGuest::SetTooltipText( 159 const base::string16& tooltip_text) { 160 platform_view_->SetTooltipText(tooltip_text); 161} 162 163void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped( 164 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 165 int gpu_host_id) { 166 if (!guest_) 167 return; 168 169 // If accelerated surface buffers are getting swapped then we're not using 170 // the software path. 171 guest_->clear_damage_buffer(); 172 FrameMsg_BuffersSwapped_Params guest_params; 173 guest_params.size = params.size; 174 guest_params.mailbox = params.mailbox; 175 guest_params.gpu_route_id = params.route_id; 176 guest_params.gpu_host_id = gpu_host_id; 177 guest_->SendMessageToEmbedder( 178 new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(), 179 guest_params)); 180} 181 182void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer( 183 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, 184 int gpu_host_id) { 185 NOTREACHED(); 186} 187 188void RenderWidgetHostViewGuest::OnSwapCompositorFrame( 189 uint32 output_surface_id, 190 scoped_ptr<cc::CompositorFrame> frame) { 191 if (!guest_) 192 return; 193 194 guest_->clear_damage_buffer(); 195 196 if (!guest_->attached()) { 197 // If the guest doesn't have an embedder then there's nothing to give the 198 // the frame to. 199 return; 200 } 201 base::SharedMemoryHandle software_frame_handle = 202 base::SharedMemory::NULLHandle(); 203 if (frame->software_frame_data) { 204 cc::SoftwareFrameData* frame_data = frame->software_frame_data.get(); 205 scoped_ptr<cc::SharedBitmap> bitmap = 206 HostSharedBitmapManager::current()->GetSharedBitmapFromId( 207 frame_data->size, frame_data->bitmap_id); 208 if (!bitmap) 209 return; 210 211 RenderWidgetHostView* embedder_rwhv = 212 guest_->GetEmbedderRenderWidgetHostView(); 213 base::ProcessHandle embedder_pid = 214 embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle(); 215 216 bitmap->memory()->ShareToProcess(embedder_pid, &software_frame_handle); 217 } 218 219 FrameMsg_CompositorFrameSwapped_Params guest_params; 220 frame->AssignTo(&guest_params.frame); 221 guest_params.output_surface_id = output_surface_id; 222 guest_params.producing_route_id = host_->GetRoutingID(); 223 guest_params.producing_host_id = host_->GetProcess()->GetID(); 224 guest_params.shared_memory_handle = software_frame_handle; 225 226 guest_->SendMessageToEmbedder( 227 new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(), 228 guest_params)); 229} 230 231bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) { 232 return platform_view_->OnMessageReceived(msg); 233} 234 235void RenderWidgetHostViewGuest::InitAsChild( 236 gfx::NativeView parent_view) { 237 platform_view_->InitAsChild(parent_view); 238} 239 240void RenderWidgetHostViewGuest::InitAsPopup( 241 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { 242 // This should never get called. 243 NOTREACHED(); 244} 245 246void RenderWidgetHostViewGuest::InitAsFullscreen( 247 RenderWidgetHostView* reference_host_view) { 248 // This should never get called. 249 NOTREACHED(); 250} 251 252gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const { 253 if (!guest_) 254 return gfx::NativeView(); 255 256 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 257 if (!rwhv) 258 return gfx::NativeView(); 259 return rwhv->GetNativeView(); 260} 261 262gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const { 263 if (!guest_) 264 return static_cast<gfx::NativeViewId>(NULL); 265 266 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 267 if (!rwhv) 268 return static_cast<gfx::NativeViewId>(NULL); 269 return rwhv->GetNativeViewId(); 270} 271 272gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() { 273 if (!guest_) 274 return gfx::NativeViewAccessible(); 275 276 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 277 if (!rwhv) 278 return gfx::NativeViewAccessible(); 279 return rwhv->GetNativeViewAccessible(); 280} 281 282void RenderWidgetHostViewGuest::MovePluginWindows( 283 const gfx::Vector2d& scroll_offset, 284 const std::vector<WebPluginGeometry>& moves) { 285 platform_view_->MovePluginWindows(scroll_offset, moves); 286} 287 288void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) { 289 platform_view_->UpdateCursor(cursor); 290} 291 292void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) { 293 platform_view_->SetIsLoading(is_loading); 294} 295 296void RenderWidgetHostViewGuest::TextInputTypeChanged( 297 ui::TextInputType type, 298 ui::TextInputMode input_mode, 299 bool can_compose_inline) { 300 if (!guest_) 301 return; 302 303 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV( 304 guest_->GetEmbedderRenderWidgetHostView()); 305 if (!rwhv) 306 return; 307 // Forward the information to embedding RWHV. 308 rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline); 309} 310 311void RenderWidgetHostViewGuest::ImeCancelComposition() { 312 if (!guest_) 313 return; 314 315 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV( 316 guest_->GetEmbedderRenderWidgetHostView()); 317 if (!rwhv) 318 return; 319 // Forward the information to embedding RWHV. 320 rwhv->ImeCancelComposition(); 321} 322 323#if defined(OS_MACOSX) || defined(USE_AURA) 324void RenderWidgetHostViewGuest::ImeCompositionRangeChanged( 325 const gfx::Range& range, 326 const std::vector<gfx::Rect>& character_bounds) { 327 if (!guest_) 328 return; 329 330 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV( 331 guest_->GetEmbedderRenderWidgetHostView()); 332 if (!rwhv) 333 return; 334 std::vector<gfx::Rect> guest_character_bounds; 335 for (size_t i = 0; i < character_bounds.size(); ++i) { 336 gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]); 337 guest_character_bounds.push_back(guest_rect); 338 } 339 // Forward the information to embedding RWHV. 340 rwhv->ImeCompositionRangeChanged(range, guest_character_bounds); 341} 342#endif 343 344void RenderWidgetHostViewGuest::DidUpdateBackingStore( 345 const gfx::Rect& scroll_rect, 346 const gfx::Vector2d& scroll_delta, 347 const std::vector<gfx::Rect>& copy_rects, 348 const std::vector<ui::LatencyInfo>& latency_info) { 349 NOTREACHED(); 350} 351 352void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text, 353 size_t offset, 354 const gfx::Range& range) { 355 platform_view_->SelectionChanged(text, offset, range); 356} 357 358void RenderWidgetHostViewGuest::SelectionBoundsChanged( 359 const ViewHostMsg_SelectionBounds_Params& params) { 360 if (!guest_) 361 return; 362 363 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV( 364 guest_->GetEmbedderRenderWidgetHostView()); 365 if (!rwhv) 366 return; 367 ViewHostMsg_SelectionBounds_Params guest_params(params); 368 guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect); 369 guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect); 370 rwhv->SelectionBoundsChanged(guest_params); 371} 372 373#if defined(OS_ANDROID) 374void RenderWidgetHostViewGuest::SelectionRootBoundsChanged( 375 const gfx::Rect& bounds) { 376 if (!guest_) 377 return; 378 379 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV( 380 guest_->GetEmbedderRenderWidgetHostView()); 381 if (!rwhv) 382 return; 383 384 rwhv->SelectionRootBoundsChanged(guest_->ToGuestRect(bounds)); 385} 386#endif 387 388void RenderWidgetHostViewGuest::CopyFromCompositingSurface( 389 const gfx::Rect& src_subrect, 390 const gfx::Size& dst_size, 391 const base::Callback<void(bool, const SkBitmap&)>& callback, 392 const SkBitmap::Config config) { 393 CHECK(guest_); 394 guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback); 395} 396 397void RenderWidgetHostViewGuest::SetBackground(const SkBitmap& background) { 398 platform_view_->SetBackground(background); 399} 400 401void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar( 402 bool has_horizontal_scrollbar) { 403 platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar); 404} 405 406void RenderWidgetHostViewGuest::SetScrollOffsetPinning( 407 bool is_pinned_to_left, bool is_pinned_to_right) { 408 platform_view_->SetScrollOffsetPinning( 409 is_pinned_to_left, is_pinned_to_right); 410} 411 412bool RenderWidgetHostViewGuest::LockMouse() { 413 return platform_view_->LockMouse(); 414} 415 416void RenderWidgetHostViewGuest::UnlockMouse() { 417 return platform_view_->UnlockMouse(); 418} 419 420void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) { 421 if (!guest_) 422 return; 423 RenderWidgetHostViewPort* embedder_view = 424 RenderWidgetHostViewPort::FromRWHV( 425 guest_->GetEmbedderRenderWidgetHostView()); 426 if (embedder_view) 427 embedder_view->GetScreenInfo(results); 428} 429 430#if defined(OS_MACOSX) 431void RenderWidgetHostViewGuest::SetActive(bool active) { 432 platform_view_->SetActive(active); 433} 434 435void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) { 436 platform_view_->SetTakesFocusOnlyOnMouseDown(flag); 437} 438 439void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) { 440 platform_view_->SetWindowVisibility(visible); 441} 442 443void RenderWidgetHostViewGuest::WindowFrameChanged() { 444 platform_view_->WindowFrameChanged(); 445} 446 447void RenderWidgetHostViewGuest::ShowDefinitionForSelection() { 448 if (!guest_) 449 return; 450 451 gfx::Point origin; 452 gfx::Rect guest_bounds = GetViewBounds(); 453 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 454 gfx::Rect embedder_bounds; 455 if (rwhv) 456 embedder_bounds = rwhv->GetViewBounds(); 457 458 gfx::Vector2d guest_offset = gfx::Vector2d( 459 // Horizontal offset of guest from embedder. 460 guest_bounds.x() - embedder_bounds.x(), 461 // Vertical offset from guest's top to embedder's bottom edge. 462 embedder_bounds.bottom() - guest_bounds.y()); 463 464 RenderWidgetHostViewMacDictionaryHelper helper(platform_view_); 465 helper.SetTargetView(rwhv); 466 helper.set_offset(guest_offset); 467 helper.ShowDefinitionForSelection(); 468} 469 470bool RenderWidgetHostViewGuest::SupportsSpeech() const { 471 return platform_view_->SupportsSpeech(); 472} 473 474void RenderWidgetHostViewGuest::SpeakSelection() { 475 platform_view_->SpeakSelection(); 476} 477 478bool RenderWidgetHostViewGuest::IsSpeaking() const { 479 return platform_view_->IsSpeaking(); 480} 481 482void RenderWidgetHostViewGuest::StopSpeaking() { 483 platform_view_->StopSpeaking(); 484} 485 486bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme( 487 const NativeWebKeyboardEvent& event) { 488 return false; 489} 490 491#endif // defined(OS_MACOSX) 492 493#if defined(OS_ANDROID) 494void RenderWidgetHostViewGuest::ShowDisambiguationPopup( 495 const gfx::Rect& target_rect, 496 const SkBitmap& zoomed_bitmap) { 497} 498#endif // defined(OS_ANDROID) 499 500#if defined(OS_WIN) 501void RenderWidgetHostViewGuest::SetParentNativeViewAccessible( 502 gfx::NativeViewAccessible accessible_parent) { 503} 504 505gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin() 506 const { 507 return NULL; 508} 509#endif 510 511void RenderWidgetHostViewGuest::DestroyGuestView() { 512 host_->SetView(NULL); 513 host_ = NULL; 514 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 515} 516 517bool RenderWidgetHostViewGuest::CanDispatchToConsumer( 518 ui::GestureConsumer* consumer) { 519 CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this); 520 return true; 521} 522 523void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent( 524 ui::GestureEvent* event) { 525 ForwardGestureEventToRenderer(event); 526} 527 528void RenderWidgetHostViewGuest::DispatchCancelTouchEvent( 529 ui::TouchEvent* event) { 530 if (!host_) 531 return; 532 533 blink::WebTouchEvent cancel_event; 534 cancel_event.type = blink::WebInputEvent::TouchCancel; 535 cancel_event.timeStampSeconds = event->time_stamp().InSecondsF(); 536 host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency()); 537} 538 539bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer( 540 ui::GestureEvent* gesture) { 541#if defined(USE_AURA) 542 if (!host_) 543 return false; 544 545 if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN || 546 gesture->type() == ui::ET_GESTURE_PINCH_UPDATE || 547 gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) { 548 return true; 549 } 550 551 blink::WebGestureEvent web_gesture = 552 MakeWebGestureEventFromUIEvent(*gesture); 553 const gfx::Point& client_point = gesture->location(); 554 const gfx::Point& screen_point = gesture->location(); 555 556 web_gesture.x = client_point.x(); 557 web_gesture.y = client_point.y(); 558 web_gesture.globalX = screen_point.x(); 559 web_gesture.globalY = screen_point.y(); 560 561 if (web_gesture.type == blink::WebGestureEvent::Undefined) 562 return false; 563 if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) { 564 host_->ForwardGestureEvent( 565 CreateFlingCancelEvent(gesture->time_stamp().InSecondsF())); 566 } 567 host_->ForwardGestureEvent(web_gesture); 568 return true; 569#else 570 return false; 571#endif 572} 573 574void RenderWidgetHostViewGuest::ProcessGestures( 575 ui::GestureRecognizer::Gestures* gestures) { 576 if ((gestures == NULL) || gestures->empty()) 577 return; 578 for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin(); 579 g_it != gestures->end(); 580 ++g_it) { 581 ForwardGestureEventToRenderer(*g_it); 582 } 583} 584 585SkBitmap::Config RenderWidgetHostViewGuest::PreferredReadbackFormat() { 586 return SkBitmap::kARGB_8888_Config; 587} 588 589} // namespace content 590