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/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"
23 #if defined(OS_MACOSX)
24 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
28 #include "content/browser/renderer_host/ui_events_helper.h"
36 blink::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
;
43 #endif // defined(USE_AURA)
47 RenderWidgetHostViewGuest::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
) {
56 gesture_recognizer_
.reset(ui::GestureRecognizer::Create());
57 gesture_recognizer_
->AddGestureEventHelper(this);
58 #endif // defined(USE_AURA)
61 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
63 gesture_recognizer_
->RemoveGestureEventHelper(this);
64 #endif // defined(USE_AURA)
67 void 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.
74 // |guest_| is NULL during test.
75 if ((guest_
&& guest_
->is_in_destruction()) || !host_
->is_hidden())
77 host_
->WasShown(ui::LatencyInfo());
80 void RenderWidgetHostViewGuest::WasHidden() {
81 // |guest_| is NULL during test.
82 if ((guest_
&& guest_
->is_in_destruction()) || host_
->is_hidden())
87 void RenderWidgetHostViewGuest::SetSize(const gfx::Size
& size
) {
92 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect
& rect
) {
97 void 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
))
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 if (!ui::GestureRecognizer::Get()->ProcessTouchEventPreDispatch(*(*iter
),
116 scoped_ptr
<ui::GestureRecognizer::Gestures
> gestures
;
117 gestures
.reset(ui::GestureRecognizer::Get()->ProcessTouchEventPostDispatch(
118 *(*iter
), result
, this));
119 ProcessGestures(gestures
.get());
124 gfx::Rect
RenderWidgetHostViewGuest::GetViewBounds() const {
128 RenderWidgetHostViewBase
* rwhv
= GetGuestRenderWidgetHostView();
129 gfx::Rect embedder_bounds
;
131 embedder_bounds
= rwhv
->GetViewBounds();
132 gfx::Rect shifted_rect
= guest_
->ToGuestRect(embedder_bounds
);
133 shifted_rect
.set_width(size_
.width());
134 shifted_rect
.set_height(size_
.height());
138 void RenderWidgetHostViewGuest::RenderProcessGone(
139 base::TerminationStatus status
,
141 platform_view_
->RenderProcessGone(status
, error_code
);
142 // Destroy the guest view instance only, so we don't end up calling
143 // platform_view_->Destroy().
147 void RenderWidgetHostViewGuest::Destroy() {
148 // The RenderWidgetHost's destruction led here, so don't call it.
151 platform_view_
->Destroy();
154 gfx::Size
RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
155 return RenderWidgetHostViewBase::GetPhysicalBackingSize();
158 base::string16
RenderWidgetHostViewGuest::GetSelectedText() const {
159 return platform_view_
->GetSelectedText();
162 void RenderWidgetHostViewGuest::SetTooltipText(
163 const base::string16
& tooltip_text
) {
164 platform_view_
->SetTooltipText(tooltip_text
);
167 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
168 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
,
173 FrameMsg_BuffersSwapped_Params guest_params
;
174 guest_params
.size
= params
.size
;
175 guest_params
.mailbox
= params
.mailbox
;
176 guest_params
.gpu_route_id
= params
.route_id
;
177 guest_params
.gpu_host_id
= gpu_host_id
;
178 guest_
->SendMessageToEmbedder(
179 new BrowserPluginMsg_BuffersSwapped(guest_
->browser_plugin_instance_id(),
183 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
184 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
,
189 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
190 uint32 output_surface_id
,
191 scoped_ptr
<cc::CompositorFrame
> frame
) {
195 if (!guest_
->attached()) {
196 // If the guest doesn't have an embedder then there's nothing to give the
200 base::SharedMemoryHandle software_frame_handle
=
201 base::SharedMemory::NULLHandle();
202 if (frame
->software_frame_data
) {
203 cc::SoftwareFrameData
* frame_data
= frame
->software_frame_data
.get();
204 scoped_ptr
<cc::SharedBitmap
> bitmap
=
205 HostSharedBitmapManager::current()->GetSharedBitmapFromId(
206 frame_data
->size
, frame_data
->bitmap_id
);
210 RenderWidgetHostView
* embedder_rwhv
=
211 guest_
->GetEmbedderRenderWidgetHostView();
212 base::ProcessHandle embedder_pid
=
213 embedder_rwhv
->GetRenderWidgetHost()->GetProcess()->GetHandle();
215 bitmap
->memory()->ShareToProcess(embedder_pid
, &software_frame_handle
);
218 FrameMsg_CompositorFrameSwapped_Params guest_params
;
219 frame
->AssignTo(&guest_params
.frame
);
220 guest_params
.output_surface_id
= output_surface_id
;
221 guest_params
.producing_route_id
= host_
->GetRoutingID();
222 guest_params
.producing_host_id
= host_
->GetProcess()->GetID();
223 guest_params
.shared_memory_handle
= software_frame_handle
;
225 guest_
->SendMessageToEmbedder(
226 new BrowserPluginMsg_CompositorFrameSwapped(
227 guest_
->browser_plugin_instance_id(), guest_params
));
230 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message
& msg
) {
231 return platform_view_
->OnMessageReceived(msg
);
234 void RenderWidgetHostViewGuest::InitAsChild(
235 gfx::NativeView parent_view
) {
236 platform_view_
->InitAsChild(parent_view
);
239 void RenderWidgetHostViewGuest::InitAsPopup(
240 RenderWidgetHostView
* parent_host_view
, const gfx::Rect
& pos
) {
241 // This should never get called.
245 void RenderWidgetHostViewGuest::InitAsFullscreen(
246 RenderWidgetHostView
* reference_host_view
) {
247 // This should never get called.
251 gfx::NativeView
RenderWidgetHostViewGuest::GetNativeView() const {
253 return gfx::NativeView();
255 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
257 return gfx::NativeView();
258 return rwhv
->GetNativeView();
261 gfx::NativeViewId
RenderWidgetHostViewGuest::GetNativeViewId() const {
263 return static_cast<gfx::NativeViewId
>(NULL
);
265 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
267 return static_cast<gfx::NativeViewId
>(NULL
);
268 return rwhv
->GetNativeViewId();
271 gfx::NativeViewAccessible
RenderWidgetHostViewGuest::GetNativeViewAccessible() {
273 return gfx::NativeViewAccessible();
275 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
277 return gfx::NativeViewAccessible();
278 return rwhv
->GetNativeViewAccessible();
281 void RenderWidgetHostViewGuest::MovePluginWindows(
282 const std::vector
<WebPluginGeometry
>& moves
) {
283 platform_view_
->MovePluginWindows(moves
);
286 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor
& cursor
) {
287 platform_view_
->UpdateCursor(cursor
);
290 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading
) {
291 platform_view_
->SetIsLoading(is_loading
);
294 void RenderWidgetHostViewGuest::TextInputStateChanged(
295 const ViewHostMsg_TextInputState_Params
& params
) {
299 RenderWidgetHostViewBase
* rwhv
= GetGuestRenderWidgetHostView();
302 // Forward the information to embedding RWHV.
303 rwhv
->TextInputStateChanged(params
);
306 void RenderWidgetHostViewGuest::ImeCancelComposition() {
310 RenderWidgetHostViewBase
* rwhv
= GetGuestRenderWidgetHostView();
313 // Forward the information to embedding RWHV.
314 rwhv
->ImeCancelComposition();
317 #if defined(OS_MACOSX) || defined(USE_AURA)
318 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
319 const gfx::Range
& range
,
320 const std::vector
<gfx::Rect
>& character_bounds
) {
324 RenderWidgetHostViewBase
* rwhv
= GetGuestRenderWidgetHostView();
327 std::vector
<gfx::Rect
> guest_character_bounds
;
328 for (size_t i
= 0; i
< character_bounds
.size(); ++i
) {
329 gfx::Rect guest_rect
= guest_
->ToGuestRect(character_bounds
[i
]);
330 guest_character_bounds
.push_back(guest_rect
);
332 // Forward the information to embedding RWHV.
333 rwhv
->ImeCompositionRangeChanged(range
, guest_character_bounds
);
337 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16
& text
,
339 const gfx::Range
& range
) {
340 platform_view_
->SelectionChanged(text
, offset
, range
);
343 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
344 const ViewHostMsg_SelectionBounds_Params
& params
) {
348 RenderWidgetHostViewBase
* rwhv
= GetGuestRenderWidgetHostView();
351 ViewHostMsg_SelectionBounds_Params
guest_params(params
);
352 guest_params
.anchor_rect
= guest_
->ToGuestRect(params
.anchor_rect
);
353 guest_params
.focus_rect
= guest_
->ToGuestRect(params
.focus_rect
);
354 rwhv
->SelectionBoundsChanged(guest_params
);
357 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
358 const gfx::Rect
& src_subrect
,
359 const gfx::Size
& dst_size
,
360 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
361 const SkColorType color_type
) {
363 guest_
->CopyFromCompositingSurface(src_subrect
, dst_size
, callback
);
366 void RenderWidgetHostViewGuest::SetBackgroundOpaque(bool opaque
) {
367 platform_view_
->SetBackgroundOpaque(opaque
);
370 bool RenderWidgetHostViewGuest::LockMouse() {
371 return platform_view_
->LockMouse();
374 void RenderWidgetHostViewGuest::UnlockMouse() {
375 return platform_view_
->UnlockMouse();
378 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo
* results
) {
381 RenderWidgetHostViewBase
* embedder_view
= GetGuestRenderWidgetHostView();
383 embedder_view
->GetScreenInfo(results
);
386 #if defined(OS_MACOSX)
387 void RenderWidgetHostViewGuest::SetActive(bool active
) {
388 platform_view_
->SetActive(active
);
391 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag
) {
392 platform_view_
->SetTakesFocusOnlyOnMouseDown(flag
);
395 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible
) {
396 platform_view_
->SetWindowVisibility(visible
);
399 void RenderWidgetHostViewGuest::WindowFrameChanged() {
400 platform_view_
->WindowFrameChanged();
403 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
408 gfx::Rect guest_bounds
= GetViewBounds();
409 RenderWidgetHostView
* rwhv
= guest_
->GetEmbedderRenderWidgetHostView();
410 gfx::Rect embedder_bounds
;
412 embedder_bounds
= rwhv
->GetViewBounds();
414 gfx::Vector2d guest_offset
= gfx::Vector2d(
415 // Horizontal offset of guest from embedder.
416 guest_bounds
.x() - embedder_bounds
.x(),
417 // Vertical offset from guest's top to embedder's bottom edge.
418 embedder_bounds
.bottom() - guest_bounds
.y());
420 RenderWidgetHostViewMacDictionaryHelper
helper(platform_view_
);
421 helper
.SetTargetView(rwhv
);
422 helper
.set_offset(guest_offset
);
423 helper
.ShowDefinitionForSelection();
426 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
427 return platform_view_
->SupportsSpeech();
430 void RenderWidgetHostViewGuest::SpeakSelection() {
431 platform_view_
->SpeakSelection();
434 bool RenderWidgetHostViewGuest::IsSpeaking() const {
435 return platform_view_
->IsSpeaking();
438 void RenderWidgetHostViewGuest::StopSpeaking() {
439 platform_view_
->StopSpeaking();
442 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
443 const NativeWebKeyboardEvent
& event
) {
447 #endif // defined(OS_MACOSX)
449 #if defined(OS_ANDROID)
450 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
451 const gfx::Rect
& target_rect
,
452 const SkBitmap
& zoomed_bitmap
) {
455 void RenderWidgetHostViewGuest::LockCompositingSurface() {
458 void RenderWidgetHostViewGuest::UnlockCompositingSurface() {
460 #endif // defined(OS_ANDROID)
463 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
464 gfx::NativeViewAccessible accessible_parent
) {
467 gfx::NativeViewId
RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
473 void RenderWidgetHostViewGuest::DestroyGuestView() {
474 host_
->SetView(NULL
);
476 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
479 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
480 ui::GestureConsumer
* consumer
) {
481 CHECK_EQ(static_cast<RenderWidgetHostViewGuest
*>(consumer
), this);
485 void RenderWidgetHostViewGuest::DispatchGestureEvent(
486 ui::GestureEvent
* event
) {
487 ForwardGestureEventToRenderer(event
);
490 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
491 ui::TouchEvent
* event
) {
495 blink::WebTouchEvent cancel_event
;
496 // TODO(rbyers): This event has no touches in it. Don't we need to know what
497 // touches are currently active in order to cancel them all properly?
498 WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel
,
499 event
->time_stamp().InSecondsF(),
502 host_
->ForwardTouchEventWithLatencyInfo(cancel_event
, *event
->latency());
505 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
506 ui::GestureEvent
* gesture
) {
507 #if defined(USE_AURA)
511 if ((gesture
->type() == ui::ET_GESTURE_PINCH_BEGIN
||
512 gesture
->type() == ui::ET_GESTURE_PINCH_UPDATE
||
513 gesture
->type() == ui::ET_GESTURE_PINCH_END
) && !pinch_zoom_enabled_
) {
517 blink::WebGestureEvent web_gesture
=
518 MakeWebGestureEventFromUIEvent(*gesture
);
519 const gfx::Point
& client_point
= gesture
->location();
520 const gfx::Point
& screen_point
= gesture
->location();
522 web_gesture
.x
= client_point
.x();
523 web_gesture
.y
= client_point
.y();
524 web_gesture
.globalX
= screen_point
.x();
525 web_gesture
.globalY
= screen_point
.y();
527 if (web_gesture
.type
== blink::WebGestureEvent::Undefined
)
529 if (web_gesture
.type
== blink::WebGestureEvent::GestureTapDown
) {
530 host_
->ForwardGestureEvent(
531 CreateFlingCancelEvent(gesture
->time_stamp().InSecondsF()));
533 host_
->ForwardGestureEvent(web_gesture
);
540 void RenderWidgetHostViewGuest::ProcessGestures(
541 ui::GestureRecognizer::Gestures
* gestures
) {
542 if ((gestures
== NULL
) || gestures
->empty())
544 for (ui::GestureRecognizer::Gestures::iterator g_it
= gestures
->begin();
545 g_it
!= gestures
->end();
547 ForwardGestureEventToRenderer(*g_it
);
551 SkColorType
RenderWidgetHostViewGuest::PreferredReadbackFormat() {
552 return kN32_SkColorType
;
555 RenderWidgetHostViewBase
*
556 RenderWidgetHostViewGuest::GetGuestRenderWidgetHostView() const {
557 return static_cast<RenderWidgetHostViewBase
*>(
558 guest_
->GetEmbedderRenderWidgetHostView());
561 } // namespace content