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.
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/view_messages.h"
16 #include "content/common/webplugin_geometry.h"
17 #include "content/public/common/content_switches.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
21 #if defined(OS_MACOSX)
22 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
25 #if defined(OS_WIN) || defined(USE_AURA)
26 #include "content/browser/renderer_host/ui_events_helper.h"
33 #if defined(OS_WIN) || defined(USE_AURA)
34 blink::WebGestureEvent
CreateFlingCancelEvent(double time_stamp
) {
35 blink::WebGestureEvent gesture_event
;
36 gesture_event
.timeStampSeconds
= time_stamp
;
37 gesture_event
.type
= blink::WebGestureEvent::GestureFlingCancel
;
38 gesture_event
.sourceDevice
= blink::WebGestureEvent::Touchscreen
;
41 #endif // defined(OS_WIN) || defined(USE_AURA)
45 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
46 RenderWidgetHost
* widget_host
,
47 BrowserPluginGuest
* guest
,
48 RenderWidgetHostView
* platform_view
)
49 : RenderWidgetHostViewChildFrame(widget_host
),
50 // |guest| is NULL during test.
51 guest_(guest
? guest
->AsWeakPtr() : base::WeakPtr
<BrowserPluginGuest
>()),
52 platform_view_(static_cast<RenderWidgetHostViewPort
*>(platform_view
)) {
53 #if defined(OS_WIN) || defined(USE_AURA)
54 gesture_recognizer_
.reset(ui::GestureRecognizer::Create());
55 gesture_recognizer_
->AddGestureEventHelper(this);
56 #endif // defined(OS_WIN) || defined(USE_AURA)
59 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
60 #if defined(OS_WIN) || defined(USE_AURA)
61 gesture_recognizer_
->RemoveGestureEventHelper(this);
62 #endif // defined(OS_WIN) || defined(USE_AURA)
65 void RenderWidgetHostViewGuest::WasShown() {
66 // If the WebContents associated with us showed an interstitial page in the
67 // beginning, the teardown path might call WasShown() while |host_| is in
68 // the process of destruction. Avoid calling WasShown below in this case.
69 // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
70 // first place: http://crbug.com/273089.
72 // |guest_| is NULL during test.
73 if ((guest_
&& guest_
->is_in_destruction()) || !host_
->is_hidden())
78 void RenderWidgetHostViewGuest::WasHidden() {
79 // |guest_| is NULL during test.
80 if ((guest_
&& guest_
->is_in_destruction()) || host_
->is_hidden())
85 void RenderWidgetHostViewGuest::SetSize(const gfx::Size
& size
) {
90 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect
& rect
) {
94 #if defined(OS_WIN) || defined(USE_AURA)
95 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
96 const TouchEventWithLatencyInfo
& touch
, InputEventAckState ack_result
) {
97 // TODO(fsamuel): Currently we will only take this codepath if the guest has
98 // requested touch events. A better solution is to always forward touchpresses
99 // to the embedder process to target a BrowserPlugin, and then route all
100 // subsequent touch points of that touchdown to the appropriate guest until
101 // that touch point is released.
102 ScopedVector
<ui::TouchEvent
> events
;
103 if (!MakeUITouchEventsFromWebTouchEvents(touch
, &events
, LOCAL_COORDINATES
))
106 ui::EventResult result
= (ack_result
==
107 INPUT_EVENT_ACK_STATE_CONSUMED
) ? ui::ER_HANDLED
: ui::ER_UNHANDLED
;
108 for (ScopedVector
<ui::TouchEvent
>::iterator iter
= events
.begin(),
109 end
= events
.end(); iter
!= end
; ++iter
) {
110 scoped_ptr
<ui::GestureRecognizer::Gestures
> gestures
;
111 gestures
.reset(gesture_recognizer_
->ProcessTouchEventForGesture(
112 *(*iter
), result
, this));
113 ProcessGestures(gestures
.get());
118 gfx::Rect
RenderWidgetHostViewGuest::GetViewBounds() const {
122 RenderWidgetHostViewPort
* rwhv
= static_cast<RenderWidgetHostViewPort
*>(
123 guest_
->GetEmbedderRenderWidgetHostView());
124 gfx::Rect embedder_bounds
;
126 embedder_bounds
= rwhv
->GetViewBounds();
127 gfx::Rect shifted_rect
= guest_
->ToGuestRect(embedder_bounds
);
128 shifted_rect
.set_width(size_
.width());
129 shifted_rect
.set_height(size_
.height());
133 void RenderWidgetHostViewGuest::RenderProcessGone(
134 base::TerminationStatus status
,
136 platform_view_
->RenderProcessGone(status
, error_code
);
137 // Destroy the guest view instance only, so we don't end up calling
138 // platform_view_->Destroy().
142 void RenderWidgetHostViewGuest::Destroy() {
143 // The RenderWidgetHost's destruction led here, so don't call it.
146 platform_view_
->Destroy();
149 gfx::Size
RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
150 return RenderWidgetHostViewBase::GetPhysicalBackingSize();
153 base::string16
RenderWidgetHostViewGuest::GetSelectedText() const {
154 return platform_view_
->GetSelectedText();
157 void RenderWidgetHostViewGuest::SetTooltipText(
158 const base::string16
& tooltip_text
) {
159 platform_view_
->SetTooltipText(tooltip_text
);
162 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
163 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
,
168 // If accelerated surface buffers are getting swapped then we're not using
169 // the software path.
170 guest_
->clear_damage_buffer();
171 FrameMsg_BuffersSwapped_Params guest_params
;
172 guest_params
.size
= params
.size
;
173 guest_params
.mailbox
= params
.mailbox
;
174 guest_params
.gpu_route_id
= params
.route_id
;
175 guest_params
.gpu_host_id
= gpu_host_id
;
176 guest_
->SendMessageToEmbedder(
177 new BrowserPluginMsg_BuffersSwapped(guest_
->instance_id(),
181 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
182 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
,
187 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
188 uint32 output_surface_id
,
189 scoped_ptr
<cc::CompositorFrame
> frame
) {
193 guest_
->clear_damage_buffer();
195 if (!guest_
->attached()) {
196 // If the guest doesn't have an embedder then there's nothing to give the
200 if (frame
->software_frame_data
) {
201 cc::SoftwareFrameData
* frame_data
= frame
->software_frame_data
.get();
203 base::SharedMemory
shared_memory(frame_data
->handle
, true,
204 host_
->GetProcess()->GetHandle());
206 base::SharedMemory
shared_memory(frame_data
->handle
, true);
209 RenderWidgetHostView
* embedder_rwhv
=
210 guest_
->GetEmbedderRenderWidgetHostView();
211 base::ProcessHandle embedder_pid
=
212 embedder_rwhv
->GetRenderWidgetHost()->GetProcess()->GetHandle();
214 shared_memory
.GiveToProcess(embedder_pid
, &frame_data
->handle
);
217 FrameMsg_CompositorFrameSwapped_Params guest_params
;
218 frame
->AssignTo(&guest_params
.frame
);
219 guest_params
.output_surface_id
= output_surface_id
;
220 guest_params
.producing_route_id
= host_
->GetRoutingID();
221 guest_params
.producing_host_id
= host_
->GetProcess()->GetID();
223 guest_
->SendMessageToEmbedder(
224 new BrowserPluginMsg_CompositorFrameSwapped(guest_
->instance_id(),
228 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message
& msg
) {
229 return platform_view_
->OnMessageReceived(msg
);
232 void RenderWidgetHostViewGuest::InitAsChild(
233 gfx::NativeView parent_view
) {
234 platform_view_
->InitAsChild(parent_view
);
237 void RenderWidgetHostViewGuest::InitAsPopup(
238 RenderWidgetHostView
* parent_host_view
, const gfx::Rect
& pos
) {
239 // This should never get called.
243 void RenderWidgetHostViewGuest::InitAsFullscreen(
244 RenderWidgetHostView
* reference_host_view
) {
245 // This should never get called.
249 gfx::NativeView
RenderWidgetHostViewGuest::GetNativeView() const {
251 return gfx::NativeView();
253 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
255 return gfx::NativeView();
256 return rwhv
->GetNativeView();
259 gfx::NativeViewId
RenderWidgetHostViewGuest::GetNativeViewId() const {
261 return static_cast<gfx::NativeViewId
>(NULL
);
263 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
265 return static_cast<gfx::NativeViewId
>(NULL
);
266 return rwhv
->GetNativeViewId();
269 gfx::NativeViewAccessible
RenderWidgetHostViewGuest::GetNativeViewAccessible() {
271 return gfx::NativeViewAccessible();
273 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
275 return gfx::NativeViewAccessible();
276 return rwhv
->GetNativeViewAccessible();
279 void RenderWidgetHostViewGuest::MovePluginWindows(
280 const gfx::Vector2d
& scroll_offset
,
281 const std::vector
<WebPluginGeometry
>& moves
) {
282 platform_view_
->MovePluginWindows(scroll_offset
, moves
);
285 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor
& cursor
) {
286 platform_view_
->UpdateCursor(cursor
);
289 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading
) {
290 platform_view_
->SetIsLoading(is_loading
);
293 void RenderWidgetHostViewGuest::TextInputTypeChanged(
294 ui::TextInputType type
,
295 ui::TextInputMode input_mode
,
296 bool can_compose_inline
) {
300 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
301 guest_
->GetEmbedderRenderWidgetHostView());
304 // Forward the information to embedding RWHV.
305 rwhv
->TextInputTypeChanged(type
, input_mode
, can_compose_inline
);
308 void RenderWidgetHostViewGuest::ImeCancelComposition() {
312 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
313 guest_
->GetEmbedderRenderWidgetHostView());
316 // Forward the information to embedding RWHV.
317 rwhv
->ImeCancelComposition();
320 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
321 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
322 const gfx::Range
& range
,
323 const std::vector
<gfx::Rect
>& character_bounds
) {
327 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
328 guest_
->GetEmbedderRenderWidgetHostView());
331 std::vector
<gfx::Rect
> guest_character_bounds
;
332 for (size_t i
= 0; i
< character_bounds
.size(); ++i
) {
333 gfx::Rect guest_rect
= guest_
->ToGuestRect(character_bounds
[i
]);
334 guest_character_bounds
.push_back(guest_rect
);
336 // Forward the information to embedding RWHV.
337 rwhv
->ImeCompositionRangeChanged(range
, guest_character_bounds
);
341 void RenderWidgetHostViewGuest::DidUpdateBackingStore(
342 const gfx::Rect
& scroll_rect
,
343 const gfx::Vector2d
& scroll_delta
,
344 const std::vector
<gfx::Rect
>& copy_rects
,
345 const std::vector
<ui::LatencyInfo
>& latency_info
) {
349 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16
& text
,
351 const gfx::Range
& range
) {
352 platform_view_
->SelectionChanged(text
, offset
, range
);
355 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
356 const ViewHostMsg_SelectionBounds_Params
& params
) {
360 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
361 guest_
->GetEmbedderRenderWidgetHostView());
364 ViewHostMsg_SelectionBounds_Params
guest_params(params
);
365 guest_params
.anchor_rect
= guest_
->ToGuestRect(params
.anchor_rect
);
366 guest_params
.focus_rect
= guest_
->ToGuestRect(params
.focus_rect
);
367 rwhv
->SelectionBoundsChanged(guest_params
);
370 #if defined(OS_ANDROID)
371 void RenderWidgetHostViewGuest::SelectionRootBoundsChanged(
372 const gfx::Rect
& bounds
) {
376 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
377 guest_
->GetEmbedderRenderWidgetHostView());
381 rwhv
->SelectionRootBoundsChanged(guest_
->ToGuestRect(bounds
));
385 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
386 const gfx::Rect
& src_subrect
,
387 const gfx::Size
& dst_size
,
388 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
389 const SkBitmap::Config config
) {
391 guest_
->CopyFromCompositingSurface(src_subrect
, dst_size
, callback
);
394 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap
& background
) {
395 platform_view_
->SetBackground(background
);
398 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
399 bool has_horizontal_scrollbar
) {
400 platform_view_
->SetHasHorizontalScrollbar(has_horizontal_scrollbar
);
403 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
404 bool is_pinned_to_left
, bool is_pinned_to_right
) {
405 platform_view_
->SetScrollOffsetPinning(
406 is_pinned_to_left
, is_pinned_to_right
);
409 bool RenderWidgetHostViewGuest::LockMouse() {
410 return platform_view_
->LockMouse();
413 void RenderWidgetHostViewGuest::UnlockMouse() {
414 return platform_view_
->UnlockMouse();
417 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo
* results
) {
420 RenderWidgetHostViewPort
* embedder_view
=
421 RenderWidgetHostViewPort::FromRWHV(
422 guest_
->GetEmbedderRenderWidgetHostView());
424 embedder_view
->GetScreenInfo(results
);
427 #if defined(OS_MACOSX)
428 void RenderWidgetHostViewGuest::SetActive(bool active
) {
429 platform_view_
->SetActive(active
);
432 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag
) {
433 platform_view_
->SetTakesFocusOnlyOnMouseDown(flag
);
436 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible
) {
437 platform_view_
->SetWindowVisibility(visible
);
440 void RenderWidgetHostViewGuest::WindowFrameChanged() {
441 platform_view_
->WindowFrameChanged();
444 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
449 gfx::Rect guest_bounds
= GetViewBounds();
450 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
451 gfx::Rect embedder_bounds
;
453 embedder_bounds
= rwhv
->GetViewBounds();
455 gfx::Vector2d guest_offset
= gfx::Vector2d(
456 // Horizontal offset of guest from embedder.
457 guest_bounds
.x() - embedder_bounds
.x(),
458 // Vertical offset from guest's top to embedder's bottom edge.
459 embedder_bounds
.bottom() - guest_bounds
.y());
461 RenderWidgetHostViewMacDictionaryHelper
helper(platform_view_
);
462 helper
.SetTargetView(rwhv
);
463 helper
.set_offset(guest_offset
);
464 helper
.ShowDefinitionForSelection();
467 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
468 return platform_view_
->SupportsSpeech();
471 void RenderWidgetHostViewGuest::SpeakSelection() {
472 platform_view_
->SpeakSelection();
475 bool RenderWidgetHostViewGuest::IsSpeaking() const {
476 return platform_view_
->IsSpeaking();
479 void RenderWidgetHostViewGuest::StopSpeaking() {
480 platform_view_
->StopSpeaking();
483 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
484 const NativeWebKeyboardEvent
& event
) {
488 #endif // defined(OS_MACOSX)
490 #if defined(OS_ANDROID)
491 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
492 const gfx::Rect
& target_rect
,
493 const SkBitmap
& zoomed_bitmap
) {
495 #endif // defined(OS_ANDROID)
497 #if defined(TOOLKIT_GTK)
498 GdkEventButton
* RenderWidgetHostViewGuest::GetLastMouseDown() {
502 gfx::NativeView
RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
503 return platform_view_
->BuildInputMethodsGtkMenu();
505 #endif // defined(TOOLKIT_GTK)
508 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
509 gfx::NativeViewAccessible accessible_parent
) {
512 gfx::NativeViewId
RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
518 void RenderWidgetHostViewGuest::DestroyGuestView() {
519 host_
->SetView(NULL
);
521 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
524 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
525 ui::GestureConsumer
* consumer
) {
526 CHECK_EQ(static_cast<RenderWidgetHostViewGuest
*>(consumer
), this);
530 void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent(
531 ui::GestureEvent
* event
) {
532 ForwardGestureEventToRenderer(event
);
535 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
536 ui::TouchEvent
* event
) {
540 blink::WebTouchEvent cancel_event
;
541 cancel_event
.type
= blink::WebInputEvent::TouchCancel
;
542 cancel_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
543 host_
->ForwardTouchEventWithLatencyInfo(cancel_event
, *event
->latency());
546 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
547 ui::GestureEvent
* gesture
) {
548 #if defined(OS_WIN) || defined(USE_AURA)
552 if ((gesture
->type() == ui::ET_GESTURE_PINCH_BEGIN
||
553 gesture
->type() == ui::ET_GESTURE_PINCH_UPDATE
||
554 gesture
->type() == ui::ET_GESTURE_PINCH_END
) && !pinch_zoom_enabled_
) {
558 blink::WebGestureEvent web_gesture
=
559 MakeWebGestureEventFromUIEvent(*gesture
);
560 const gfx::Point
& client_point
= gesture
->location();
561 const gfx::Point
& screen_point
= gesture
->location();
563 web_gesture
.x
= client_point
.x();
564 web_gesture
.y
= client_point
.y();
565 web_gesture
.globalX
= screen_point
.x();
566 web_gesture
.globalY
= screen_point
.y();
568 if (web_gesture
.type
== blink::WebGestureEvent::Undefined
)
570 if (web_gesture
.type
== blink::WebGestureEvent::GestureTapDown
) {
571 host_
->ForwardGestureEvent(
572 CreateFlingCancelEvent(gesture
->time_stamp().InSecondsF()));
574 host_
->ForwardGestureEvent(web_gesture
);
581 void RenderWidgetHostViewGuest::ProcessGestures(
582 ui::GestureRecognizer::Gestures
* gestures
) {
583 if ((gestures
== NULL
) || gestures
->empty())
585 for (ui::GestureRecognizer::Gestures::iterator g_it
= gestures
->begin();
586 g_it
!= gestures
->end();
588 ForwardGestureEventToRenderer(*g_it
);
592 SkBitmap::Config
RenderWidgetHostViewGuest::PreferredReadbackFormat() {
593 return SkBitmap::kARGB_8888_Config
;
596 } // namespace content