render_widget_host_view_guest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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::WebGestureDeviceTouchscreen; 41 return gesture_event; 42} 43#endif // defined(USE_AURA) 44 45} // namespace 46 47RenderWidgetHostViewGuest::RenderWidgetHostViewGuest( 48 RenderWidgetHost* widget_host, 49 BrowserPluginGuest* guest, 50 RenderWidgetHostViewBase* platform_view) 51 : RenderWidgetHostViewChildFrame(widget_host), 52 // |guest| is NULL during test. 53 guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()), 54 platform_view_(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 RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView(); 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 FrameMsg_BuffersSwapped_Params guest_params; 170 guest_params.size = params.size; 171 guest_params.mailbox = params.mailbox; 172 guest_params.gpu_route_id = params.route_id; 173 guest_params.gpu_host_id = gpu_host_id; 174 guest_->SendMessageToEmbedder( 175 new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(), 176 guest_params)); 177} 178 179void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer( 180 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, 181 int gpu_host_id) { 182 NOTREACHED(); 183} 184 185void RenderWidgetHostViewGuest::OnSwapCompositorFrame( 186 uint32 output_surface_id, 187 scoped_ptr<cc::CompositorFrame> frame) { 188 if (!guest_) 189 return; 190 191 if (!guest_->attached()) { 192 // If the guest doesn't have an embedder then there's nothing to give the 193 // the frame to. 194 return; 195 } 196 base::SharedMemoryHandle software_frame_handle = 197 base::SharedMemory::NULLHandle(); 198 if (frame->software_frame_data) { 199 cc::SoftwareFrameData* frame_data = frame->software_frame_data.get(); 200 scoped_ptr<cc::SharedBitmap> bitmap = 201 HostSharedBitmapManager::current()->GetSharedBitmapFromId( 202 frame_data->size, frame_data->bitmap_id); 203 if (!bitmap) 204 return; 205 206 RenderWidgetHostView* embedder_rwhv = 207 guest_->GetEmbedderRenderWidgetHostView(); 208 base::ProcessHandle embedder_pid = 209 embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle(); 210 211 bitmap->memory()->ShareToProcess(embedder_pid, &software_frame_handle); 212 } 213 214 FrameMsg_CompositorFrameSwapped_Params guest_params; 215 frame->AssignTo(&guest_params.frame); 216 guest_params.output_surface_id = output_surface_id; 217 guest_params.producing_route_id = host_->GetRoutingID(); 218 guest_params.producing_host_id = host_->GetProcess()->GetID(); 219 guest_params.shared_memory_handle = software_frame_handle; 220 221 guest_->SendMessageToEmbedder( 222 new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(), 223 guest_params)); 224} 225 226bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) { 227 return platform_view_->OnMessageReceived(msg); 228} 229 230void RenderWidgetHostViewGuest::InitAsChild( 231 gfx::NativeView parent_view) { 232 platform_view_->InitAsChild(parent_view); 233} 234 235void RenderWidgetHostViewGuest::InitAsPopup( 236 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { 237 // This should never get called. 238 NOTREACHED(); 239} 240 241void RenderWidgetHostViewGuest::InitAsFullscreen( 242 RenderWidgetHostView* reference_host_view) { 243 // This should never get called. 244 NOTREACHED(); 245} 246 247gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const { 248 if (!guest_) 249 return gfx::NativeView(); 250 251 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 252 if (!rwhv) 253 return gfx::NativeView(); 254 return rwhv->GetNativeView(); 255} 256 257gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const { 258 if (!guest_) 259 return static_cast<gfx::NativeViewId>(NULL); 260 261 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 262 if (!rwhv) 263 return static_cast<gfx::NativeViewId>(NULL); 264 return rwhv->GetNativeViewId(); 265} 266 267gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() { 268 if (!guest_) 269 return gfx::NativeViewAccessible(); 270 271 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 272 if (!rwhv) 273 return gfx::NativeViewAccessible(); 274 return rwhv->GetNativeViewAccessible(); 275} 276 277void RenderWidgetHostViewGuest::MovePluginWindows( 278 const std::vector<WebPluginGeometry>& moves) { 279 platform_view_->MovePluginWindows(moves); 280} 281 282void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) { 283 platform_view_->UpdateCursor(cursor); 284} 285 286void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) { 287 platform_view_->SetIsLoading(is_loading); 288} 289 290void RenderWidgetHostViewGuest::TextInputTypeChanged( 291 ui::TextInputType type, 292 ui::TextInputMode input_mode, 293 bool can_compose_inline) { 294 if (!guest_) 295 return; 296 297 RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView(); 298 if (!rwhv) 299 return; 300 // Forward the information to embedding RWHV. 301 rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline); 302} 303 304void RenderWidgetHostViewGuest::ImeCancelComposition() { 305 if (!guest_) 306 return; 307 308 RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView(); 309 if (!rwhv) 310 return; 311 // Forward the information to embedding RWHV. 312 rwhv->ImeCancelComposition(); 313} 314 315#if defined(OS_MACOSX) || defined(USE_AURA) 316void RenderWidgetHostViewGuest::ImeCompositionRangeChanged( 317 const gfx::Range& range, 318 const std::vector<gfx::Rect>& character_bounds) { 319 if (!guest_) 320 return; 321 322 RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView(); 323 if (!rwhv) 324 return; 325 std::vector<gfx::Rect> guest_character_bounds; 326 for (size_t i = 0; i < character_bounds.size(); ++i) { 327 gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]); 328 guest_character_bounds.push_back(guest_rect); 329 } 330 // Forward the information to embedding RWHV. 331 rwhv->ImeCompositionRangeChanged(range, guest_character_bounds); 332} 333#endif 334 335void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text, 336 size_t offset, 337 const gfx::Range& range) { 338 platform_view_->SelectionChanged(text, offset, range); 339} 340 341void RenderWidgetHostViewGuest::SelectionBoundsChanged( 342 const ViewHostMsg_SelectionBounds_Params& params) { 343 if (!guest_) 344 return; 345 346 RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView(); 347 if (!rwhv) 348 return; 349 ViewHostMsg_SelectionBounds_Params guest_params(params); 350 guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect); 351 guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect); 352 rwhv->SelectionBoundsChanged(guest_params); 353} 354 355void RenderWidgetHostViewGuest::CopyFromCompositingSurface( 356 const gfx::Rect& src_subrect, 357 const gfx::Size& dst_size, 358 const base::Callback<void(bool, const SkBitmap&)>& callback, 359 const SkBitmap::Config config) { 360 CHECK(guest_); 361 guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback); 362} 363 364void RenderWidgetHostViewGuest::SetBackgroundOpaque(bool opaque) { 365 platform_view_->SetBackgroundOpaque(opaque); 366} 367 368void RenderWidgetHostViewGuest::SetScrollOffsetPinning( 369 bool is_pinned_to_left, bool is_pinned_to_right) { 370 platform_view_->SetScrollOffsetPinning( 371 is_pinned_to_left, is_pinned_to_right); 372} 373 374bool RenderWidgetHostViewGuest::LockMouse() { 375 return platform_view_->LockMouse(); 376} 377 378void RenderWidgetHostViewGuest::UnlockMouse() { 379 return platform_view_->UnlockMouse(); 380} 381 382void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) { 383 if (!guest_) 384 return; 385 RenderWidgetHostViewBase* embedder_view = GetGuestRenderWidgetHostView(); 386 if (embedder_view) 387 embedder_view->GetScreenInfo(results); 388} 389 390#if defined(OS_MACOSX) 391void RenderWidgetHostViewGuest::SetActive(bool active) { 392 platform_view_->SetActive(active); 393} 394 395void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) { 396 platform_view_->SetTakesFocusOnlyOnMouseDown(flag); 397} 398 399void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) { 400 platform_view_->SetWindowVisibility(visible); 401} 402 403void RenderWidgetHostViewGuest::WindowFrameChanged() { 404 platform_view_->WindowFrameChanged(); 405} 406 407void RenderWidgetHostViewGuest::ShowDefinitionForSelection() { 408 if (!guest_) 409 return; 410 411 gfx::Point origin; 412 gfx::Rect guest_bounds = GetViewBounds(); 413 RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView(); 414 gfx::Rect embedder_bounds; 415 if (rwhv) 416 embedder_bounds = rwhv->GetViewBounds(); 417 418 gfx::Vector2d guest_offset = gfx::Vector2d( 419 // Horizontal offset of guest from embedder. 420 guest_bounds.x() - embedder_bounds.x(), 421 // Vertical offset from guest's top to embedder's bottom edge. 422 embedder_bounds.bottom() - guest_bounds.y()); 423 424 RenderWidgetHostViewMacDictionaryHelper helper(platform_view_); 425 helper.SetTargetView(rwhv); 426 helper.set_offset(guest_offset); 427 helper.ShowDefinitionForSelection(); 428} 429 430bool RenderWidgetHostViewGuest::SupportsSpeech() const { 431 return platform_view_->SupportsSpeech(); 432} 433 434void RenderWidgetHostViewGuest::SpeakSelection() { 435 platform_view_->SpeakSelection(); 436} 437 438bool RenderWidgetHostViewGuest::IsSpeaking() const { 439 return platform_view_->IsSpeaking(); 440} 441 442void RenderWidgetHostViewGuest::StopSpeaking() { 443 platform_view_->StopSpeaking(); 444} 445 446bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme( 447 const NativeWebKeyboardEvent& event) { 448 return false; 449} 450 451#endif // defined(OS_MACOSX) 452 453#if defined(OS_ANDROID) 454void RenderWidgetHostViewGuest::ShowDisambiguationPopup( 455 const gfx::Rect& target_rect, 456 const SkBitmap& zoomed_bitmap) { 457} 458 459void RenderWidgetHostViewGuest::LockCompositingSurface() { 460} 461 462void RenderWidgetHostViewGuest::UnlockCompositingSurface() { 463} 464#endif // defined(OS_ANDROID) 465 466#if defined(OS_WIN) 467void RenderWidgetHostViewGuest::SetParentNativeViewAccessible( 468 gfx::NativeViewAccessible accessible_parent) { 469} 470 471gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin() 472 const { 473 return NULL; 474} 475#endif 476 477void RenderWidgetHostViewGuest::DestroyGuestView() { 478 host_->SetView(NULL); 479 host_ = NULL; 480 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 481} 482 483bool RenderWidgetHostViewGuest::CanDispatchToConsumer( 484 ui::GestureConsumer* consumer) { 485 CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this); 486 return true; 487} 488 489void RenderWidgetHostViewGuest::DispatchGestureEvent( 490 ui::GestureEvent* event) { 491 ForwardGestureEventToRenderer(event); 492} 493 494void RenderWidgetHostViewGuest::DispatchCancelTouchEvent( 495 ui::TouchEvent* event) { 496 if (!host_) 497 return; 498 499 blink::WebTouchEvent cancel_event; 500 // TODO(rbyers): This event has no touches in it. Don't we need to know what 501 // touches are currently active in order to cancel them all properly? 502 WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel, 503 event->time_stamp().InSecondsF(), 504 &cancel_event); 505 506 host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency()); 507} 508 509bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer( 510 ui::GestureEvent* gesture) { 511#if defined(USE_AURA) 512 if (!host_) 513 return false; 514 515 if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN || 516 gesture->type() == ui::ET_GESTURE_PINCH_UPDATE || 517 gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) { 518 return true; 519 } 520 521 blink::WebGestureEvent web_gesture = 522 MakeWebGestureEventFromUIEvent(*gesture); 523 const gfx::Point& client_point = gesture->location(); 524 const gfx::Point& screen_point = gesture->location(); 525 526 web_gesture.x = client_point.x(); 527 web_gesture.y = client_point.y(); 528 web_gesture.globalX = screen_point.x(); 529 web_gesture.globalY = screen_point.y(); 530 531 if (web_gesture.type == blink::WebGestureEvent::Undefined) 532 return false; 533 if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) { 534 host_->ForwardGestureEvent( 535 CreateFlingCancelEvent(gesture->time_stamp().InSecondsF())); 536 } 537 host_->ForwardGestureEvent(web_gesture); 538 return true; 539#else 540 return false; 541#endif 542} 543 544void RenderWidgetHostViewGuest::ProcessGestures( 545 ui::GestureRecognizer::Gestures* gestures) { 546 if ((gestures == NULL) || gestures->empty()) 547 return; 548 for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin(); 549 g_it != gestures->end(); 550 ++g_it) { 551 ForwardGestureEventToRenderer(*g_it); 552 } 553} 554 555SkBitmap::Config RenderWidgetHostViewGuest::PreferredReadbackFormat() { 556 return SkBitmap::kARGB_8888_Config; 557} 558 559RenderWidgetHostViewBase* 560RenderWidgetHostViewGuest::GetGuestRenderWidgetHostView() const { 561 return static_cast<RenderWidgetHostViewBase*>( 562 guest_->GetEmbedderRenderWidgetHostView()); 563} 564 565} // namespace content 566