Fix for browser_plugin_host_browsertest when embedder is not yet available.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_guest.cc
blob87765b5cae1f1e27fbef7b812012316d6ff40371
1 // Copyright (c) 2012 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/renderer_host/render_view_host_impl.h"
11 #include "content/browser/renderer_host/render_widget_host_view_guest.h"
12 #include "content/common/browser_plugin/browser_plugin_messages.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "content/common/view_messages.h"
15 #include "content/common/webplugin_geometry.h"
16 #include "content/public/common/content_switches.h"
17 #include "skia/ext/platform_canvas.h"
18 #include "third_party/WebKit/public/web/WebScreenInfo.h"
20 #if defined(OS_MACOSX)
21 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
22 #endif
24 #if defined(OS_WIN) || defined(USE_AURA)
25 #include "content/browser/renderer_host/ui_events_helper.h"
26 #endif
28 namespace content {
30 namespace {
32 bool ShouldSendPinchGesture() {
33 static bool pinch_allowed =
34 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
35 return pinch_allowed;
38 WebKit::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
39 WebKit::WebGestureEvent gesture_event;
40 gesture_event.timeStampSeconds = time_stamp;
41 gesture_event.type = WebKit::WebGestureEvent::GestureFlingCancel;
42 gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
43 return gesture_event;
46 } // namespace
48 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
49 RenderWidgetHost* widget_host,
50 BrowserPluginGuest* guest,
51 RenderWidgetHostView* platform_view)
52 : host_(RenderWidgetHostImpl::From(widget_host)),
53 guest_(guest),
54 platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) {
55 #if defined(OS_WIN) || defined(USE_AURA)
56 gesture_recognizer_.reset(ui::GestureRecognizer::Create());
57 gesture_recognizer_->AddGestureEventHelper(this);
58 #endif // defined(OS_WIN) || defined(USE_AURA)
59 host_->SetView(this);
62 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
63 #if defined(OS_WIN) || defined(USE_AURA)
64 gesture_recognizer_->RemoveGestureEventHelper(this);
65 #endif // defined(OS_WIN) || defined(USE_AURA)
68 RenderWidgetHost* RenderWidgetHostViewGuest::GetRenderWidgetHost() const {
69 return host_;
72 void RenderWidgetHostViewGuest::WasShown() {
73 // If the WebContents associated with us showed an interstitial page in the
74 // beginning, the teardown path might call WasShown() while |host_| is in
75 // the process of destruction. Avoid calling WasShown below in this case.
76 // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
77 // first place: http://crbug.com/273089.
79 // |guest_| is NULL during test.
80 if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
81 return;
82 host_->WasShown();
85 void RenderWidgetHostViewGuest::WasHidden() {
86 // |guest_| is NULL during test.
87 if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
88 return;
89 host_->WasHidden();
92 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
93 size_ = size;
94 host_->WasResized();
97 gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
98 // We do not have any root window specific parts in this view.
99 return GetViewBounds();
102 gfx::GLSurfaceHandle RenderWidgetHostViewGuest::GetCompositingSurface() {
103 return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
106 #if defined(OS_WIN) || defined(USE_AURA)
107 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
108 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
109 // TODO(fsamuel): Currently we will only take this codepath if the guest has
110 // requested touch events. A better solution is to always forward touchpresses
111 // to the embedder process to target a BrowserPlugin, and then route all
112 // subsequent touch points of that touchdown to the appropriate guest until
113 // that touch point is released.
114 ScopedVector<ui::TouchEvent> events;
115 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
116 return;
118 ui::EventResult result = (ack_result ==
119 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
120 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
121 end = events.end(); iter != end; ++iter) {
122 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
123 gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
124 *(*iter), result, this));
125 ProcessGestures(gestures.get());
128 #endif
130 void RenderWidgetHostViewGuest::Show() {
131 WasShown();
134 void RenderWidgetHostViewGuest::Hide() {
135 WasHidden();
138 bool RenderWidgetHostViewGuest::IsShowing() {
139 return !host_->is_hidden();
142 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
143 RenderWidgetHostViewPort* rwhv = static_cast<RenderWidgetHostViewPort*>(
144 guest_->GetEmbedderRenderWidgetHostView());
145 gfx::Rect embedder_bounds;
146 if (rwhv)
147 embedder_bounds = rwhv->GetViewBounds();
148 gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
149 shifted_rect.set_width(size_.width());
150 shifted_rect.set_height(size_.height());
151 return shifted_rect;
154 void RenderWidgetHostViewGuest::RenderProcessGone(
155 base::TerminationStatus status,
156 int error_code) {
157 platform_view_->RenderProcessGone(status, error_code);
158 // Destroy the guest view instance only, so we don't end up calling
159 // platform_view_->Destroy().
160 DestroyGuestView();
163 void RenderWidgetHostViewGuest::Destroy() {
164 // The RenderWidgetHost's destruction led here, so don't call it.
165 DestroyGuestView();
167 platform_view_->Destroy();
170 void RenderWidgetHostViewGuest::SetTooltipText(const string16& tooltip_text) {
171 platform_view_->SetTooltipText(tooltip_text);
174 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
175 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
176 int gpu_host_id) {
177 // If accelerated surface buffers are getting swapped then we're not using
178 // the software path.
179 guest_->clear_damage_buffer();
180 BrowserPluginMsg_BuffersSwapped_Params guest_params;
181 guest_params.size = params.size;
182 guest_params.mailbox_name = params.mailbox_name;
183 guest_params.route_id = params.route_id;
184 guest_params.host_id = gpu_host_id;
185 guest_->SendMessageToEmbedder(
186 new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(), guest_params));
189 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
190 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
191 int gpu_host_id) {
192 NOTREACHED();
195 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
196 uint32 output_surface_id,
197 scoped_ptr<cc::CompositorFrame> frame) {
198 if (frame->software_frame_data) {
199 cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
200 #ifdef OS_WIN
201 base::SharedMemory shared_memory(frame_data->handle, true,
202 host_->GetProcess()->GetHandle());
203 #else
204 base::SharedMemory shared_memory(frame_data->handle, true);
205 #endif
207 RenderWidgetHostView* embedder_view =
208 guest_->GetEmbedderRenderWidgetHostView();
209 base::ProcessHandle embedder_pid =
210 embedder_view->GetRenderWidgetHost()->GetProcess()->GetHandle();
212 shared_memory.GiveToProcess(embedder_pid, &frame_data->handle);
215 guest_->clear_damage_buffer();
216 guest_->SendMessageToEmbedder(
217 new BrowserPluginMsg_CompositorFrameSwapped(
218 guest_->instance_id(),
219 *frame,
220 host_->GetRoutingID(),
221 output_surface_id,
222 host_->GetProcess()->GetID()));
225 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
226 SetSize(rect.size());
229 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
230 return platform_view_->OnMessageReceived(msg);
233 void RenderWidgetHostViewGuest::InitAsChild(
234 gfx::NativeView parent_view) {
235 platform_view_->InitAsChild(parent_view);
238 void RenderWidgetHostViewGuest::InitAsPopup(
239 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
240 // This should never get called.
241 NOTREACHED();
244 void RenderWidgetHostViewGuest::InitAsFullscreen(
245 RenderWidgetHostView* reference_host_view) {
246 // This should never get called.
247 NOTREACHED();
250 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
251 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeView();
254 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
255 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewId();
258 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
259 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewAccessible();
262 void RenderWidgetHostViewGuest::MovePluginWindows(
263 const gfx::Vector2d& scroll_offset,
264 const std::vector<WebPluginGeometry>& moves) {
265 platform_view_->MovePluginWindows(scroll_offset, moves);
268 void RenderWidgetHostViewGuest::Focus() {
271 void RenderWidgetHostViewGuest::Blur() {
274 bool RenderWidgetHostViewGuest::HasFocus() const {
275 return false;
278 bool RenderWidgetHostViewGuest::IsSurfaceAvailableForCopy() const {
279 NOTIMPLEMENTED();
280 return false;
283 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
284 platform_view_->UpdateCursor(cursor);
287 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
288 platform_view_->SetIsLoading(is_loading);
291 void RenderWidgetHostViewGuest::TextInputTypeChanged(
292 ui::TextInputType type,
293 ui::TextInputMode input_mode,
294 bool can_compose_inline) {
295 RenderWidgetHostViewPort::FromRWHV(
296 guest_->GetEmbedderRenderWidgetHostView())->
297 TextInputTypeChanged(type, input_mode, can_compose_inline);
300 void RenderWidgetHostViewGuest::ImeCancelComposition() {
301 platform_view_->ImeCancelComposition();
304 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
305 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
306 const gfx::Range& range,
307 const std::vector<gfx::Rect>& character_bounds) {
309 #endif
311 void RenderWidgetHostViewGuest::DidUpdateBackingStore(
312 const gfx::Rect& scroll_rect,
313 const gfx::Vector2d& scroll_delta,
314 const std::vector<gfx::Rect>& copy_rects,
315 const ui::LatencyInfo& latency_info) {
316 NOTREACHED();
319 void RenderWidgetHostViewGuest::SelectionChanged(const string16& text,
320 size_t offset,
321 const gfx::Range& range) {
322 platform_view_->SelectionChanged(text, offset, range);
325 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
326 const ViewHostMsg_SelectionBounds_Params& params) {
327 platform_view_->SelectionBoundsChanged(params);
330 void RenderWidgetHostViewGuest::ScrollOffsetChanged() {
333 BackingStore* RenderWidgetHostViewGuest::AllocBackingStore(
334 const gfx::Size& size) {
335 NOTREACHED();
336 return NULL;
339 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
340 const gfx::Rect& src_subrect,
341 const gfx::Size& /* dst_size */,
342 const base::Callback<void(bool, const SkBitmap&)>& callback) {
343 callback.Run(false, SkBitmap());
346 void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame(
347 const gfx::Rect& src_subrect,
348 const scoped_refptr<media::VideoFrame>& target,
349 const base::Callback<void(bool)>& callback) {
350 NOTIMPLEMENTED();
351 callback.Run(false);
354 bool RenderWidgetHostViewGuest::CanCopyToVideoFrame() const {
355 return false;
358 void RenderWidgetHostViewGuest::AcceleratedSurfaceSuspend() {
359 NOTREACHED();
362 void RenderWidgetHostViewGuest::AcceleratedSurfaceRelease() {
365 bool RenderWidgetHostViewGuest::HasAcceleratedSurface(
366 const gfx::Size& desired_size) {
367 return false;
370 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap& background) {
371 platform_view_->SetBackground(background);
374 #if defined(OS_WIN) && !defined(USE_AURA)
375 void RenderWidgetHostViewGuest::SetClickthroughRegion(SkRegion* region) {
377 #endif
379 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
380 bool has_horizontal_scrollbar) {
381 platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
384 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
385 bool is_pinned_to_left, bool is_pinned_to_right) {
386 platform_view_->SetScrollOffsetPinning(
387 is_pinned_to_left, is_pinned_to_right);
390 void RenderWidgetHostViewGuest::OnAcceleratedCompositingStateChange() {
393 bool RenderWidgetHostViewGuest::LockMouse() {
394 return platform_view_->LockMouse();
397 void RenderWidgetHostViewGuest::UnlockMouse() {
398 return platform_view_->UnlockMouse();
401 void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
402 RenderWidgetHostViewPort* embedder_view =
403 RenderWidgetHostViewPort::FromRWHV(
404 guest_->GetEmbedderRenderWidgetHostView());
405 if (embedder_view)
406 embedder_view->GetScreenInfo(results);
409 void RenderWidgetHostViewGuest::OnAccessibilityEvents(
410 const std::vector<AccessibilityHostMsg_EventParams>& params) {
413 #if defined(OS_MACOSX)
414 void RenderWidgetHostViewGuest::SetActive(bool active) {
415 platform_view_->SetActive(active);
418 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
419 platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
422 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
423 platform_view_->SetWindowVisibility(visible);
426 void RenderWidgetHostViewGuest::WindowFrameChanged() {
427 platform_view_->WindowFrameChanged();
430 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
431 gfx::Point origin;
432 gfx::Rect guest_bounds = GetViewBounds();
433 gfx::Rect embedder_bounds =
434 guest_->GetEmbedderRenderWidgetHostView()->GetViewBounds();
436 gfx::Vector2d guest_offset = gfx::Vector2d(
437 // Horizontal offset of guest from embedder.
438 guest_bounds.x() - embedder_bounds.x(),
439 // Vertical offset from guest's top to embedder's bottom edge.
440 embedder_bounds.bottom() - guest_bounds.y());
442 RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
443 helper.SetTargetView(guest_->GetEmbedderRenderWidgetHostView());
444 helper.set_offset(guest_offset);
445 helper.ShowDefinitionForSelection();
448 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
449 return platform_view_->SupportsSpeech();
452 void RenderWidgetHostViewGuest::SpeakSelection() {
453 platform_view_->SpeakSelection();
456 bool RenderWidgetHostViewGuest::IsSpeaking() const {
457 return platform_view_->IsSpeaking();
460 void RenderWidgetHostViewGuest::StopSpeaking() {
461 platform_view_->StopSpeaking();
464 void RenderWidgetHostViewGuest::AboutToWaitForBackingStoreMsg() {
465 NOTREACHED();
468 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
469 const NativeWebKeyboardEvent& event) {
470 return false;
473 #endif // defined(OS_MACOSX)
475 #if defined(OS_ANDROID)
476 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
477 const gfx::Rect& target_rect,
478 const SkBitmap& zoomed_bitmap) {
481 void RenderWidgetHostViewGuest::HasTouchEventHandlers(bool need_touch_events) {
483 #endif // defined(OS_ANDROID)
485 #if defined(TOOLKIT_GTK)
486 GdkEventButton* RenderWidgetHostViewGuest::GetLastMouseDown() {
487 return NULL;
490 gfx::NativeView RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
491 return platform_view_->BuildInputMethodsGtkMenu();
493 #endif // defined(TOOLKIT_GTK)
495 #if defined(OS_WIN) && !defined(USE_AURA)
496 void RenderWidgetHostViewGuest::WillWmDestroy() {
498 #endif
500 #if defined(OS_WIN) && defined(USE_AURA)
501 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
502 gfx::NativeViewAccessible accessible_parent) {
504 #endif
506 void RenderWidgetHostViewGuest::DestroyGuestView() {
507 host_->SetView(NULL);
508 host_ = NULL;
509 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
512 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
513 ui::GestureConsumer* consumer) {
514 CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
515 return true;
518 void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent(
519 ui::GestureEvent* event) {
520 ForwardGestureEventToRenderer(event);
523 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
524 ui::TouchEvent* event) {
525 if (!host_)
526 return;
528 WebKit::WebTouchEvent cancel_event;
529 cancel_event.type = WebKit::WebInputEvent::TouchCancel;
530 cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
531 host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
534 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
535 ui::GestureEvent* gesture) {
536 #if defined(OS_WIN) || defined(USE_AURA)
537 if (!host_)
538 return false;
540 // Pinch gestures are disabled by default on windows desktop. See
541 // crbug.com/128477 and crbug.com/148816
542 if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
543 gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
544 gesture->type() == ui::ET_GESTURE_PINCH_END) &&
545 !ShouldSendPinchGesture()) {
546 return true;
549 WebKit::WebGestureEvent web_gesture =
550 MakeWebGestureEventFromUIEvent(*gesture);
551 const gfx::Point& client_point = gesture->location();
552 const gfx::Point& screen_point = gesture->location();
554 web_gesture.x = client_point.x();
555 web_gesture.y = client_point.y();
556 web_gesture.globalX = screen_point.x();
557 web_gesture.globalY = screen_point.y();
559 if (web_gesture.type == WebKit::WebGestureEvent::Undefined)
560 return false;
561 if (web_gesture.type == WebKit::WebGestureEvent::GestureTapDown) {
562 host_->ForwardGestureEvent(
563 CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
565 host_->ForwardGestureEvent(web_gesture);
566 return true;
567 #else
568 return false;
569 #endif
572 void RenderWidgetHostViewGuest::ProcessGestures(
573 ui::GestureRecognizer::Gestures* gestures) {
574 if ((gestures == NULL) || gestures->empty())
575 return;
576 for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
577 g_it != gestures->end();
578 ++g_it) {
579 ForwardGestureEventToRenderer(*g_it);
584 } // namespace content