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