Upstream version 5.34.92.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/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"
20
21 #if defined(OS_MACOSX)
22 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
23 #endif
24
25 #if defined(OS_WIN) || defined(USE_AURA)
26 #include "content/browser/renderer_host/ui_events_helper.h"
27 #endif
28
29 namespace content {
30
31 namespace {
32
33 #if defined(OS_WIN) || defined(USE_AURA)
34 bool ShouldSendPinchGesture() {
35   static bool pinch_allowed =
36       CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
37   return pinch_allowed;
38 }
39
40 blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
41   blink::WebGestureEvent gesture_event;
42   gesture_event.timeStampSeconds = time_stamp;
43   gesture_event.type = blink::WebGestureEvent::GestureFlingCancel;
44   gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen;
45   return gesture_event;
46 }
47 #endif  // defined(OS_WIN) || defined(USE_AURA)
48
49 }  // namespace
50
51 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
52     RenderWidgetHost* widget_host,
53     BrowserPluginGuest* guest,
54     RenderWidgetHostView* platform_view)
55     : RenderWidgetHostViewChildFrame(widget_host),
56       guest_(guest),
57       platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) {
58 #if defined(OS_WIN) || defined(USE_AURA)
59   gesture_recognizer_.reset(ui::GestureRecognizer::Create());
60   gesture_recognizer_->AddGestureEventHelper(this);
61 #endif  // defined(OS_WIN) || defined(USE_AURA)
62 }
63
64 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
65 #if defined(OS_WIN) || defined(USE_AURA)
66   gesture_recognizer_->RemoveGestureEventHelper(this);
67 #endif  // defined(OS_WIN) || defined(USE_AURA)
68 }
69
70 void RenderWidgetHostViewGuest::WasShown() {
71   // If the WebContents associated with us showed an interstitial page in the
72   // beginning, the teardown path might call WasShown() while |host_| is in
73   // the process of destruction. Avoid calling WasShown below in this case.
74   // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
75   // first place: http://crbug.com/273089.
76   //
77   // |guest_| is NULL during test.
78   if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
79     return;
80   host_->WasShown();
81 }
82
83 void RenderWidgetHostViewGuest::WasHidden() {
84   // |guest_| is NULL during test.
85   if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
86     return;
87   host_->WasHidden();
88 }
89
90 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
91   size_ = size;
92   host_->WasResized();
93 }
94
95 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
96   SetSize(rect.size());
97 }
98
99 #if defined(OS_WIN) || defined(USE_AURA)
100 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
101     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
102   // TODO(fsamuel): Currently we will only take this codepath if the guest has
103   // requested touch events. A better solution is to always forward touchpresses
104   // to the embedder process to target a BrowserPlugin, and then route all
105   // subsequent touch points of that touchdown to the appropriate guest until
106   // that touch point is released.
107   ScopedVector<ui::TouchEvent> events;
108   if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
109     return;
110
111   ui::EventResult result = (ack_result ==
112       INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
113   for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
114       end = events.end(); iter != end; ++iter)  {
115     scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
116     gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
117         *(*iter), result, this));
118     ProcessGestures(gestures.get());
119   }
120 }
121 #endif
122
123 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
124   RenderWidgetHostViewPort* rwhv = static_cast<RenderWidgetHostViewPort*>(
125       guest_->GetEmbedderRenderWidgetHostView());
126   gfx::Rect embedder_bounds;
127   if (rwhv)
128     embedder_bounds = rwhv->GetViewBounds();
129   gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
130   shifted_rect.set_width(size_.width());
131   shifted_rect.set_height(size_.height());
132   return shifted_rect;
133 }
134
135 void RenderWidgetHostViewGuest::RenderProcessGone(
136     base::TerminationStatus status,
137     int error_code) {
138   platform_view_->RenderProcessGone(status, error_code);
139   // Destroy the guest view instance only, so we don't end up calling
140   // platform_view_->Destroy().
141   DestroyGuestView();
142 }
143
144 void RenderWidgetHostViewGuest::Destroy() {
145   // The RenderWidgetHost's destruction led here, so don't call it.
146   DestroyGuestView();
147
148   platform_view_->Destroy();
149 }
150
151 gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
152   return RenderWidgetHostViewBase::GetPhysicalBackingSize();
153 }
154
155 void RenderWidgetHostViewGuest::SetTooltipText(
156     const base::string16& tooltip_text) {
157   platform_view_->SetTooltipText(tooltip_text);
158 }
159
160 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
161     const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
162     int gpu_host_id) {
163   // If accelerated surface buffers are getting swapped then we're not using
164   // the software path.
165   guest_->clear_damage_buffer();
166   FrameMsg_BuffersSwapped_Params guest_params;
167   guest_params.size = params.size;
168   guest_params.mailbox_name = params.mailbox_name;
169   guest_params.gpu_route_id = params.route_id;
170   guest_params.gpu_host_id = gpu_host_id;
171   guest_->SendMessageToEmbedder(
172       new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(),
173                                           guest_params));
174 }
175
176 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
177     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
178     int gpu_host_id) {
179   NOTREACHED();
180 }
181
182 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
183     uint32 output_surface_id,
184     scoped_ptr<cc::CompositorFrame> frame) {
185   guest_->clear_damage_buffer();
186
187   if (!guest_->attached()) {
188     // If the guest doesn't have an embedder then there's nothing to give the
189     // the frame to.
190     return;
191   }
192   if (frame->software_frame_data) {
193     cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
194 #ifdef OS_WIN
195     base::SharedMemory shared_memory(frame_data->handle, true,
196                                      host_->GetProcess()->GetHandle());
197 #else
198     base::SharedMemory shared_memory(frame_data->handle, true);
199 #endif
200
201     RenderWidgetHostView* embedder_rwhv =
202         guest_->GetEmbedderRenderWidgetHostView();
203     base::ProcessHandle embedder_pid =
204         embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle();
205
206     shared_memory.GiveToProcess(embedder_pid, &frame_data->handle);
207   }
208
209   FrameMsg_CompositorFrameSwapped_Params guest_params;
210   frame->AssignTo(&guest_params.frame);
211   guest_params.output_surface_id = output_surface_id;
212   guest_params.producing_route_id = host_->GetRoutingID();
213   guest_params.producing_host_id = host_->GetProcess()->GetID();
214
215   guest_->SendMessageToEmbedder(
216       new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(),
217                                                   guest_params));
218 }
219
220 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
221   return platform_view_->OnMessageReceived(msg);
222 }
223
224 void RenderWidgetHostViewGuest::InitAsChild(
225     gfx::NativeView parent_view) {
226   platform_view_->InitAsChild(parent_view);
227 }
228
229 void RenderWidgetHostViewGuest::InitAsPopup(
230     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
231   // This should never get called.
232   NOTREACHED();
233 }
234
235 void RenderWidgetHostViewGuest::InitAsFullscreen(
236     RenderWidgetHostView* reference_host_view) {
237   // This should never get called.
238   NOTREACHED();
239 }
240
241 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
242   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
243   if (!rwhv)
244     return gfx::NativeView();
245   return rwhv->GetNativeView();
246 }
247
248 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
249   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
250   if (!rwhv)
251     return static_cast<gfx::NativeViewId>(NULL);
252   return rwhv->GetNativeViewId();
253 }
254
255 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
256   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
257   if (!rwhv)
258     return gfx::NativeViewAccessible();
259   return rwhv->GetNativeViewAccessible();
260 }
261
262 void RenderWidgetHostViewGuest::MovePluginWindows(
263     const gfx::Vector2d& scroll_offset,
264     const std::vector<WebPluginGeometry>& moves) {
265   platform_view_->MovePluginWindows(scroll_offset, moves);
266 }
267
268 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
269   platform_view_->UpdateCursor(cursor);
270 }
271
272 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
273   platform_view_->SetIsLoading(is_loading);
274 }
275
276 void RenderWidgetHostViewGuest::TextInputTypeChanged(
277     ui::TextInputType type,
278     ui::TextInputMode input_mode,
279     bool can_compose_inline) {
280   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
281       guest_->GetEmbedderRenderWidgetHostView());
282   if (!rwhv)
283     return;
284   // Forward the information to embedding RWHV.
285   rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline);
286 }
287
288 void RenderWidgetHostViewGuest::ImeCancelComposition() {
289   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
290       guest_->GetEmbedderRenderWidgetHostView());
291   if (!rwhv)
292     return;
293   // Forward the information to embedding RWHV.
294   rwhv->ImeCancelComposition();
295 }
296
297 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
298 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
299     const gfx::Range& range,
300     const std::vector<gfx::Rect>& character_bounds) {
301   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
302       guest_->GetEmbedderRenderWidgetHostView());
303   if (!rwhv)
304     return;
305   std::vector<gfx::Rect> guest_character_bounds;
306   for (size_t i = 0; i < character_bounds.size(); ++i) {
307     gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]);
308     guest_character_bounds.push_back(guest_rect);
309   }
310   // Forward the information to embedding RWHV.
311   rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
312 }
313 #endif
314
315 void RenderWidgetHostViewGuest::DidUpdateBackingStore(
316     const gfx::Rect& scroll_rect,
317     const gfx::Vector2d& scroll_delta,
318     const std::vector<gfx::Rect>& copy_rects,
319     const std::vector<ui::LatencyInfo>& latency_info) {
320   NOTREACHED();
321 }
322
323 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
324                                                  size_t offset,
325                                                  const gfx::Range& range) {
326   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
327       guest_->GetEmbedderRenderWidgetHostView());
328   if (!rwhv)
329     return;
330   // Forward the information to embedding RWHV.
331   rwhv->SelectionChanged(text, offset, range);
332 }
333
334 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
335     const ViewHostMsg_SelectionBounds_Params& params) {
336   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
337       guest_->GetEmbedderRenderWidgetHostView());
338   if (!rwhv)
339     return;
340   ViewHostMsg_SelectionBounds_Params guest_params(params);
341   guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect);
342   guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect);
343   rwhv->SelectionBoundsChanged(guest_params);
344 }
345
346 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
347     const gfx::Rect& src_subrect,
348     const gfx::Size& dst_size,
349     const base::Callback<void(bool, const SkBitmap&)>& callback,
350     const SkBitmap::Config config) {
351   CHECK(guest_);
352   guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
353 }
354
355 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap& background) {
356   platform_view_->SetBackground(background);
357 }
358
359 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
360     bool has_horizontal_scrollbar) {
361   platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
362 }
363
364 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
365     bool is_pinned_to_left, bool is_pinned_to_right) {
366   platform_view_->SetScrollOffsetPinning(
367       is_pinned_to_left, is_pinned_to_right);
368 }
369
370 bool RenderWidgetHostViewGuest::LockMouse() {
371   return platform_view_->LockMouse();
372 }
373
374 void RenderWidgetHostViewGuest::UnlockMouse() {
375   return platform_view_->UnlockMouse();
376 }
377
378 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
379   RenderWidgetHostViewPort* embedder_view =
380       RenderWidgetHostViewPort::FromRWHV(
381           guest_->GetEmbedderRenderWidgetHostView());
382   if (embedder_view)
383     embedder_view->GetScreenInfo(results);
384 }
385
386 #if defined(OS_MACOSX)
387 void RenderWidgetHostViewGuest::SetActive(bool active) {
388   platform_view_->SetActive(active);
389 }
390
391 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
392   platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
393 }
394
395 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
396   platform_view_->SetWindowVisibility(visible);
397 }
398
399 void RenderWidgetHostViewGuest::WindowFrameChanged() {
400   platform_view_->WindowFrameChanged();
401 }
402
403 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
404   gfx::Point origin;
405   gfx::Rect guest_bounds = GetViewBounds();
406   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
407   gfx::Rect embedder_bounds;
408   if (rwhv)
409     embedder_bounds = rwhv->GetViewBounds();
410
411   gfx::Vector2d guest_offset = gfx::Vector2d(
412       // Horizontal offset of guest from embedder.
413       guest_bounds.x() - embedder_bounds.x(),
414       // Vertical offset from guest's top to embedder's bottom edge.
415       embedder_bounds.bottom() - guest_bounds.y());
416
417   RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
418   helper.SetTargetView(rwhv);
419   helper.set_offset(guest_offset);
420   helper.ShowDefinitionForSelection();
421 }
422
423 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
424   return platform_view_->SupportsSpeech();
425 }
426
427 void RenderWidgetHostViewGuest::SpeakSelection() {
428   platform_view_->SpeakSelection();
429 }
430
431 bool RenderWidgetHostViewGuest::IsSpeaking() const {
432   return platform_view_->IsSpeaking();
433 }
434
435 void RenderWidgetHostViewGuest::StopSpeaking() {
436   platform_view_->StopSpeaking();
437 }
438
439 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
440     const NativeWebKeyboardEvent& event) {
441   return false;
442 }
443
444 #endif  // defined(OS_MACOSX)
445
446 #if defined(OS_ANDROID)
447 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
448     const gfx::Rect& target_rect,
449     const SkBitmap& zoomed_bitmap) {
450 }
451
452 void RenderWidgetHostViewGuest::HasTouchEventHandlers(bool need_touch_events) {
453 }
454 #endif  // defined(OS_ANDROID)
455
456 #if defined(TOOLKIT_GTK)
457 GdkEventButton* RenderWidgetHostViewGuest::GetLastMouseDown() {
458   return NULL;
459 }
460
461 gfx::NativeView RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
462   return platform_view_->BuildInputMethodsGtkMenu();
463 }
464 #endif  // defined(TOOLKIT_GTK)
465
466 #if defined(OS_WIN)
467 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
468     gfx::NativeViewAccessible accessible_parent) {
469 }
470
471 gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
472     const {
473   return NULL;
474 }
475 #endif
476
477 void RenderWidgetHostViewGuest::DestroyGuestView() {
478   host_->SetView(NULL);
479   host_ = NULL;
480   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
481 }
482
483 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
484     ui::GestureConsumer* consumer) {
485   CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
486   return true;
487 }
488
489 void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent(
490     ui::GestureEvent* event) {
491   ForwardGestureEventToRenderer(event);
492 }
493
494 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
495     ui::TouchEvent* event) {
496   if (!host_)
497     return;
498
499   blink::WebTouchEvent cancel_event;
500   cancel_event.type = blink::WebInputEvent::TouchCancel;
501   cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
502   host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
503 }
504
505 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
506     ui::GestureEvent* gesture) {
507 #if defined(OS_WIN) || defined(USE_AURA)
508   if (!host_)
509     return false;
510
511   // Pinch gestures are disabled by default on windows desktop. See
512   // crbug.com/128477 and crbug.com/148816
513   if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
514       gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
515       gesture->type() == ui::ET_GESTURE_PINCH_END) &&
516       !ShouldSendPinchGesture()) {
517     return true;
518   }
519
520   blink::WebGestureEvent web_gesture =
521       MakeWebGestureEventFromUIEvent(*gesture);
522   const gfx::Point& client_point = gesture->location();
523   const gfx::Point& screen_point = gesture->location();
524
525   web_gesture.x = client_point.x();
526   web_gesture.y = client_point.y();
527   web_gesture.globalX = screen_point.x();
528   web_gesture.globalY = screen_point.y();
529
530   if (web_gesture.type == blink::WebGestureEvent::Undefined)
531     return false;
532   if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
533     host_->ForwardGestureEvent(
534         CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
535   }
536   host_->ForwardGestureEvent(web_gesture);
537   return true;
538 #else
539   return false;
540 #endif
541 }
542
543 void RenderWidgetHostViewGuest::ProcessGestures(
544     ui::GestureRecognizer::Gestures* gestures) {
545   if ((gestures == NULL) || gestures->empty())
546     return;
547   for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
548       g_it != gestures->end();
549       ++g_it) {
550     ForwardGestureEventToRenderer(*g_it);
551   }
552 }
553
554
555 }  // namespace content