Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / content / browser / frame_host / render_widget_host_view_guest.cc
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
31 namespace content {
32
33 namespace {
34
35 #if defined(USE_AURA)
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;
41   return gesture_event;
42 }
43 #endif  // defined(USE_AURA)
44
45 }  // namespace
46
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) {
55 #if defined(USE_AURA)
56   gesture_recognizer_.reset(ui::GestureRecognizer::Create());
57   gesture_recognizer_->AddGestureEventHelper(this);
58 #endif  // defined(USE_AURA)
59 }
60
61 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
62 #if defined(USE_AURA)
63   gesture_recognizer_->RemoveGestureEventHelper(this);
64 #endif  // defined(USE_AURA)
65 }
66
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.
73   //
74   // |guest_| is NULL during test.
75   if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
76     return;
77   host_->WasShown(ui::LatencyInfo());
78 }
79
80 void 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
87 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
88   size_ = size;
89   host_->WasResized();
90 }
91
92 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
93   SetSize(rect.size());
94 }
95
96 #if defined(USE_AURA)
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))
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     if (!gesture_recognizer_->ProcessTouchEventPreDispatch(*(*iter), this))
113       continue;
114
115     scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
116     gestures.reset(gesture_recognizer_->ProcessTouchEventPostDispatch(
117         *(*iter), result, this));
118     ProcessGestures(gestures.get());
119   }
120 }
121 #endif
122
123 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
124   if (!guest_)
125     return gfx::Rect();
126
127   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
128   gfx::Rect embedder_bounds;
129   if (rwhv)
130     embedder_bounds = rwhv->GetViewBounds();
131   gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
132   shifted_rect.set_width(size_.width());
133   shifted_rect.set_height(size_.height());
134   return shifted_rect;
135 }
136
137 void RenderWidgetHostViewGuest::RenderProcessGone(
138     base::TerminationStatus status,
139     int error_code) {
140   platform_view_->RenderProcessGone(status, error_code);
141   // Destroy the guest view instance only, so we don't end up calling
142   // platform_view_->Destroy().
143   DestroyGuestView();
144 }
145
146 void RenderWidgetHostViewGuest::Destroy() {
147   // The RenderWidgetHost's destruction led here, so don't call it.
148   DestroyGuestView();
149
150   platform_view_->Destroy();
151 }
152
153 gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
154   return RenderWidgetHostViewBase::GetPhysicalBackingSize();
155 }
156
157 base::string16 RenderWidgetHostViewGuest::GetSelectedText() const {
158   return platform_view_->GetSelectedText();
159 }
160
161 void RenderWidgetHostViewGuest::SetTooltipText(
162     const base::string16& tooltip_text) {
163   platform_view_->SetTooltipText(tooltip_text);
164 }
165
166 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
167     const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
168     int gpu_host_id) {
169   if (!guest_)
170     return;
171
172   FrameMsg_BuffersSwapped_Params guest_params;
173   guest_params.size = params.size;
174   guest_params.mailbox = params.mailbox;
175   guest_params.gpu_route_id = params.route_id;
176   guest_params.gpu_host_id = gpu_host_id;
177   guest_->SendMessageToEmbedder(
178       new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(),
179                                           guest_params));
180 }
181
182 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
183     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
184     int gpu_host_id) {
185   NOTREACHED();
186 }
187
188 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
189     uint32 output_surface_id,
190     scoped_ptr<cc::CompositorFrame> frame) {
191   if (!guest_)
192     return;
193
194   if (!guest_->attached()) {
195     // If the guest doesn't have an embedder then there's nothing to give the
196     // the frame to.
197     return;
198   }
199   base::SharedMemoryHandle software_frame_handle =
200       base::SharedMemory::NULLHandle();
201   if (frame->software_frame_data) {
202     cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
203     scoped_ptr<cc::SharedBitmap> bitmap =
204         HostSharedBitmapManager::current()->GetSharedBitmapFromId(
205             frame_data->size, frame_data->bitmap_id);
206     if (!bitmap)
207       return;
208
209     RenderWidgetHostView* embedder_rwhv =
210         guest_->GetEmbedderRenderWidgetHostView();
211     base::ProcessHandle embedder_pid =
212         embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle();
213
214     bitmap->memory()->ShareToProcess(embedder_pid, &software_frame_handle);
215   }
216
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();
222   guest_params.shared_memory_handle = software_frame_handle;
223
224   guest_->SendMessageToEmbedder(
225       new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(),
226                                                   guest_params));
227 }
228
229 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
230   return platform_view_->OnMessageReceived(msg);
231 }
232
233 void RenderWidgetHostViewGuest::InitAsChild(
234     gfx::NativeView parent_view) {
235   platform_view_->InitAsChild(parent_view);
236 }
237
238 void RenderWidgetHostViewGuest::InitAsPopup(
239     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
240   // This should never get called.
241   NOTREACHED();
242 }
243
244 void RenderWidgetHostViewGuest::InitAsFullscreen(
245     RenderWidgetHostView* reference_host_view) {
246   // This should never get called.
247   NOTREACHED();
248 }
249
250 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
251   if (!guest_)
252     return gfx::NativeView();
253
254   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
255   if (!rwhv)
256     return gfx::NativeView();
257   return rwhv->GetNativeView();
258 }
259
260 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
261   if (!guest_)
262     return static_cast<gfx::NativeViewId>(NULL);
263
264   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
265   if (!rwhv)
266     return static_cast<gfx::NativeViewId>(NULL);
267   return rwhv->GetNativeViewId();
268 }
269
270 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
271   if (!guest_)
272     return gfx::NativeViewAccessible();
273
274   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
275   if (!rwhv)
276     return gfx::NativeViewAccessible();
277   return rwhv->GetNativeViewAccessible();
278 }
279
280 void RenderWidgetHostViewGuest::MovePluginWindows(
281     const std::vector<WebPluginGeometry>& moves) {
282   platform_view_->MovePluginWindows(moves);
283 }
284
285 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
286   platform_view_->UpdateCursor(cursor);
287 }
288
289 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
290   platform_view_->SetIsLoading(is_loading);
291 }
292
293 void RenderWidgetHostViewGuest::TextInputStateChanged(
294     const ViewHostMsg_TextInputState_Params& params) {
295   if (!guest_)
296     return;
297
298   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
299   if (!rwhv)
300     return;
301   // Forward the information to embedding RWHV.
302   rwhv->TextInputStateChanged(params);
303 }
304
305 void RenderWidgetHostViewGuest::ImeCancelComposition() {
306   if (!guest_)
307     return;
308
309   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
310   if (!rwhv)
311     return;
312   // Forward the information to embedding RWHV.
313   rwhv->ImeCancelComposition();
314 }
315
316 #if defined(OS_MACOSX) || defined(USE_AURA)
317 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
318     const gfx::Range& range,
319     const std::vector<gfx::Rect>& character_bounds) {
320   if (!guest_)
321     return;
322
323   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
324   if (!rwhv)
325     return;
326   std::vector<gfx::Rect> guest_character_bounds;
327   for (size_t i = 0; i < character_bounds.size(); ++i) {
328     gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]);
329     guest_character_bounds.push_back(guest_rect);
330   }
331   // Forward the information to embedding RWHV.
332   rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
333 }
334 #endif
335
336 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
337                                                  size_t offset,
338                                                  const gfx::Range& range) {
339   platform_view_->SelectionChanged(text, offset, range);
340 }
341
342 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
343     const ViewHostMsg_SelectionBounds_Params& params) {
344   if (!guest_)
345     return;
346
347   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
348   if (!rwhv)
349     return;
350   ViewHostMsg_SelectionBounds_Params guest_params(params);
351   guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect);
352   guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect);
353   rwhv->SelectionBoundsChanged(guest_params);
354 }
355
356 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
357     const gfx::Rect& src_subrect,
358     const gfx::Size& dst_size,
359     const base::Callback<void(bool, const SkBitmap&)>& callback,
360     const SkColorType color_type) {
361   CHECK(guest_);
362   guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
363 }
364
365 void RenderWidgetHostViewGuest::SetBackgroundOpaque(bool opaque) {
366   platform_view_->SetBackgroundOpaque(opaque);
367 }
368
369 bool RenderWidgetHostViewGuest::LockMouse() {
370   return platform_view_->LockMouse();
371 }
372
373 void RenderWidgetHostViewGuest::UnlockMouse() {
374   return platform_view_->UnlockMouse();
375 }
376
377 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
378   if (!guest_)
379     return;
380   RenderWidgetHostViewBase* embedder_view = GetGuestRenderWidgetHostView();
381   if (embedder_view)
382     embedder_view->GetScreenInfo(results);
383 }
384
385 #if defined(OS_MACOSX)
386 void RenderWidgetHostViewGuest::SetActive(bool active) {
387   platform_view_->SetActive(active);
388 }
389
390 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
391   platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
392 }
393
394 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
395   platform_view_->SetWindowVisibility(visible);
396 }
397
398 void RenderWidgetHostViewGuest::WindowFrameChanged() {
399   platform_view_->WindowFrameChanged();
400 }
401
402 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
403   if (!guest_)
404     return;
405
406   gfx::Point origin;
407   gfx::Rect guest_bounds = GetViewBounds();
408   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
409   gfx::Rect embedder_bounds;
410   if (rwhv)
411     embedder_bounds = rwhv->GetViewBounds();
412
413   gfx::Vector2d guest_offset = gfx::Vector2d(
414       // Horizontal offset of guest from embedder.
415       guest_bounds.x() - embedder_bounds.x(),
416       // Vertical offset from guest's top to embedder's bottom edge.
417       embedder_bounds.bottom() - guest_bounds.y());
418
419   RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
420   helper.SetTargetView(rwhv);
421   helper.set_offset(guest_offset);
422   helper.ShowDefinitionForSelection();
423 }
424
425 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
426   return platform_view_->SupportsSpeech();
427 }
428
429 void RenderWidgetHostViewGuest::SpeakSelection() {
430   platform_view_->SpeakSelection();
431 }
432
433 bool RenderWidgetHostViewGuest::IsSpeaking() const {
434   return platform_view_->IsSpeaking();
435 }
436
437 void RenderWidgetHostViewGuest::StopSpeaking() {
438   platform_view_->StopSpeaking();
439 }
440
441 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
442     const NativeWebKeyboardEvent& event) {
443   return false;
444 }
445
446 #endif  // defined(OS_MACOSX)
447
448 #if defined(OS_ANDROID)
449 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
450     const gfx::Rect& target_rect,
451     const SkBitmap& zoomed_bitmap) {
452 }
453
454 void RenderWidgetHostViewGuest::LockCompositingSurface() {
455 }
456
457 void RenderWidgetHostViewGuest::UnlockCompositingSurface() {
458 }
459 #endif  // defined(OS_ANDROID)
460
461 #if defined(OS_WIN)
462 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
463     gfx::NativeViewAccessible accessible_parent) {
464 }
465
466 gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
467     const {
468   return NULL;
469 }
470 #endif
471
472 void RenderWidgetHostViewGuest::DestroyGuestView() {
473   host_->SetView(NULL);
474   host_ = NULL;
475   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
476 }
477
478 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
479     ui::GestureConsumer* consumer) {
480   CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
481   return true;
482 }
483
484 void RenderWidgetHostViewGuest::DispatchGestureEvent(
485     ui::GestureEvent* event) {
486   ForwardGestureEventToRenderer(event);
487 }
488
489 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
490     ui::TouchEvent* event) {
491   if (!host_)
492     return;
493
494   blink::WebTouchEvent cancel_event;
495   // TODO(rbyers): This event has no touches in it.  Don't we need to know what
496   // touches are currently active in order to cancel them all properly?
497   WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel,
498                                  event->time_stamp().InSecondsF(),
499                                  &cancel_event);
500
501   host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
502 }
503
504 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
505     ui::GestureEvent* gesture) {
506 #if defined(USE_AURA)
507   if (!host_)
508     return false;
509
510   if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
511       gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
512       gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
513     return true;
514   }
515
516   blink::WebGestureEvent web_gesture =
517       MakeWebGestureEventFromUIEvent(*gesture);
518   const gfx::Point& client_point = gesture->location();
519   const gfx::Point& screen_point = gesture->location();
520
521   web_gesture.x = client_point.x();
522   web_gesture.y = client_point.y();
523   web_gesture.globalX = screen_point.x();
524   web_gesture.globalY = screen_point.y();
525
526   if (web_gesture.type == blink::WebGestureEvent::Undefined)
527     return false;
528   if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
529     host_->ForwardGestureEvent(
530         CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
531   }
532   host_->ForwardGestureEvent(web_gesture);
533   return true;
534 #else
535   return false;
536 #endif
537 }
538
539 void RenderWidgetHostViewGuest::ProcessGestures(
540     ui::GestureRecognizer::Gestures* gestures) {
541   if ((gestures == NULL) || gestures->empty())
542     return;
543   for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
544       g_it != gestures->end();
545       ++g_it) {
546     ForwardGestureEventToRenderer(*g_it);
547   }
548 }
549
550 SkColorType RenderWidgetHostViewGuest::PreferredReadbackFormat() {
551   return kN32_SkColorType;
552 }
553
554 RenderWidgetHostViewBase*
555 RenderWidgetHostViewGuest::GetGuestRenderWidgetHostView() const {
556   return static_cast<RenderWidgetHostViewBase*>(
557       guest_->GetEmbedderRenderWidgetHostView());
558 }
559
560 }  // namespace content