Upstream version 5.34.104.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 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;
39   return gesture_event;
40 }
41 #endif  // defined(OS_WIN) || defined(USE_AURA)
42
43 }  // namespace
44
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)
57 }
58
59 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
60 #if defined(OS_WIN) || defined(USE_AURA)
61   gesture_recognizer_->RemoveGestureEventHelper(this);
62 #endif  // defined(OS_WIN) || defined(USE_AURA)
63 }
64
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.
71   //
72   // |guest_| is NULL during test.
73   if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
74     return;
75   host_->WasShown();
76 }
77
78 void RenderWidgetHostViewGuest::WasHidden() {
79   // |guest_| is NULL during test.
80   if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
81     return;
82   host_->WasHidden();
83 }
84
85 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
86   size_ = size;
87   host_->WasResized();
88 }
89
90 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
91   SetSize(rect.size());
92 }
93
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))
104     return;
105
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());
114   }
115 }
116 #endif
117
118 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
119   if (!guest_)
120     return gfx::Rect();
121
122   RenderWidgetHostViewPort* rwhv = static_cast<RenderWidgetHostViewPort*>(
123       guest_->GetEmbedderRenderWidgetHostView());
124   gfx::Rect embedder_bounds;
125   if (rwhv)
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());
130   return shifted_rect;
131 }
132
133 void RenderWidgetHostViewGuest::RenderProcessGone(
134     base::TerminationStatus status,
135     int error_code) {
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().
139   DestroyGuestView();
140 }
141
142 void RenderWidgetHostViewGuest::Destroy() {
143   // The RenderWidgetHost's destruction led here, so don't call it.
144   DestroyGuestView();
145
146   platform_view_->Destroy();
147 }
148
149 gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
150   return RenderWidgetHostViewBase::GetPhysicalBackingSize();
151 }
152
153 base::string16 RenderWidgetHostViewGuest::GetSelectedText() const {
154   return platform_view_->GetSelectedText();
155 }
156
157 void RenderWidgetHostViewGuest::SetTooltipText(
158     const base::string16& tooltip_text) {
159   platform_view_->SetTooltipText(tooltip_text);
160 }
161
162 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
163     const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
164     int gpu_host_id) {
165   if (!guest_)
166     return;
167
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(),
178                                           guest_params));
179 }
180
181 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
182     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
183     int gpu_host_id) {
184   NOTREACHED();
185 }
186
187 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
188     uint32 output_surface_id,
189     scoped_ptr<cc::CompositorFrame> frame) {
190   if (!guest_)
191     return;
192
193   guest_->clear_damage_buffer();
194
195   if (!guest_->attached()) {
196     // If the guest doesn't have an embedder then there's nothing to give the
197     // the frame to.
198     return;
199   }
200   if (frame->software_frame_data) {
201     cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
202 #ifdef OS_WIN
203     base::SharedMemory shared_memory(frame_data->handle, true,
204                                      host_->GetProcess()->GetHandle());
205 #else
206     base::SharedMemory shared_memory(frame_data->handle, true);
207 #endif
208
209     RenderWidgetHostView* embedder_rwhv =
210         guest_->GetEmbedderRenderWidgetHostView();
211     base::ProcessHandle embedder_pid =
212         embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle();
213
214     shared_memory.GiveToProcess(embedder_pid, &frame_data->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
223   guest_->SendMessageToEmbedder(
224       new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(),
225                                                   guest_params));
226 }
227
228 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
229   return platform_view_->OnMessageReceived(msg);
230 }
231
232 void RenderWidgetHostViewGuest::InitAsChild(
233     gfx::NativeView parent_view) {
234   platform_view_->InitAsChild(parent_view);
235 }
236
237 void RenderWidgetHostViewGuest::InitAsPopup(
238     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
239   // This should never get called.
240   NOTREACHED();
241 }
242
243 void RenderWidgetHostViewGuest::InitAsFullscreen(
244     RenderWidgetHostView* reference_host_view) {
245   // This should never get called.
246   NOTREACHED();
247 }
248
249 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
250   if (!guest_)
251     return gfx::NativeView();
252
253   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
254   if (!rwhv)
255     return gfx::NativeView();
256   return rwhv->GetNativeView();
257 }
258
259 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
260   if (!guest_)
261     return static_cast<gfx::NativeViewId>(NULL);
262
263   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
264   if (!rwhv)
265     return static_cast<gfx::NativeViewId>(NULL);
266   return rwhv->GetNativeViewId();
267 }
268
269 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
270   if (!guest_)
271     return gfx::NativeViewAccessible();
272
273   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
274   if (!rwhv)
275     return gfx::NativeViewAccessible();
276   return rwhv->GetNativeViewAccessible();
277 }
278
279 void RenderWidgetHostViewGuest::MovePluginWindows(
280     const gfx::Vector2d& scroll_offset,
281     const std::vector<WebPluginGeometry>& moves) {
282   platform_view_->MovePluginWindows(scroll_offset, 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::TextInputTypeChanged(
294     ui::TextInputType type,
295     ui::TextInputMode input_mode,
296     bool can_compose_inline) {
297   if (!guest_)
298     return;
299
300   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
301       guest_->GetEmbedderRenderWidgetHostView());
302   if (!rwhv)
303     return;
304   // Forward the information to embedding RWHV.
305   rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline);
306 }
307
308 void RenderWidgetHostViewGuest::ImeCancelComposition() {
309   if (!guest_)
310     return;
311
312   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
313       guest_->GetEmbedderRenderWidgetHostView());
314   if (!rwhv)
315     return;
316   // Forward the information to embedding RWHV.
317   rwhv->ImeCancelComposition();
318 }
319
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) {
324   if (!guest_)
325     return;
326
327   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
328       guest_->GetEmbedderRenderWidgetHostView());
329   if (!rwhv)
330     return;
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);
335   }
336   // Forward the information to embedding RWHV.
337   rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
338 }
339 #endif
340
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) {
346   NOTREACHED();
347 }
348
349 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
350                                                  size_t offset,
351                                                  const gfx::Range& range) {
352   platform_view_->SelectionChanged(text, offset, range);
353 }
354
355 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
356     const ViewHostMsg_SelectionBounds_Params& params) {
357   if (!guest_)
358     return;
359
360   RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
361       guest_->GetEmbedderRenderWidgetHostView());
362   if (!rwhv)
363     return;
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);
368 }
369
370 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
371     const gfx::Rect& src_subrect,
372     const gfx::Size& dst_size,
373     const base::Callback<void(bool, const SkBitmap&)>& callback,
374     const SkBitmap::Config config) {
375   CHECK(guest_);
376   guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
377 }
378
379 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap& background) {
380   platform_view_->SetBackground(background);
381 }
382
383 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
384     bool has_horizontal_scrollbar) {
385   platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
386 }
387
388 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
389     bool is_pinned_to_left, bool is_pinned_to_right) {
390   platform_view_->SetScrollOffsetPinning(
391       is_pinned_to_left, is_pinned_to_right);
392 }
393
394 bool RenderWidgetHostViewGuest::LockMouse() {
395   return platform_view_->LockMouse();
396 }
397
398 void RenderWidgetHostViewGuest::UnlockMouse() {
399   return platform_view_->UnlockMouse();
400 }
401
402 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
403   if (!guest_)
404     return;
405   RenderWidgetHostViewPort* embedder_view =
406       RenderWidgetHostViewPort::FromRWHV(
407           guest_->GetEmbedderRenderWidgetHostView());
408   if (embedder_view)
409     embedder_view->GetScreenInfo(results);
410 }
411
412 #if defined(OS_MACOSX)
413 void RenderWidgetHostViewGuest::SetActive(bool active) {
414   platform_view_->SetActive(active);
415 }
416
417 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
418   platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
419 }
420
421 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
422   platform_view_->SetWindowVisibility(visible);
423 }
424
425 void RenderWidgetHostViewGuest::WindowFrameChanged() {
426   platform_view_->WindowFrameChanged();
427 }
428
429 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
430   if (!guest_)
431     return;
432
433   gfx::Point origin;
434   gfx::Rect guest_bounds = GetViewBounds();
435   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
436   gfx::Rect embedder_bounds;
437   if (rwhv)
438     embedder_bounds = rwhv->GetViewBounds();
439
440   gfx::Vector2d guest_offset = gfx::Vector2d(
441       // Horizontal offset of guest from embedder.
442       guest_bounds.x() - embedder_bounds.x(),
443       // Vertical offset from guest's top to embedder's bottom edge.
444       embedder_bounds.bottom() - guest_bounds.y());
445
446   RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
447   helper.SetTargetView(rwhv);
448   helper.set_offset(guest_offset);
449   helper.ShowDefinitionForSelection();
450 }
451
452 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
453   return platform_view_->SupportsSpeech();
454 }
455
456 void RenderWidgetHostViewGuest::SpeakSelection() {
457   platform_view_->SpeakSelection();
458 }
459
460 bool RenderWidgetHostViewGuest::IsSpeaking() const {
461   return platform_view_->IsSpeaking();
462 }
463
464 void RenderWidgetHostViewGuest::StopSpeaking() {
465   platform_view_->StopSpeaking();
466 }
467
468 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
469     const NativeWebKeyboardEvent& event) {
470   return false;
471 }
472
473 #endif  // defined(OS_MACOSX)
474
475 #if defined(OS_ANDROID)
476 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
477     const gfx::Rect& target_rect,
478     const SkBitmap& zoomed_bitmap) {
479 }
480 #endif  // defined(OS_ANDROID)
481
482 #if defined(TOOLKIT_GTK)
483 GdkEventButton* RenderWidgetHostViewGuest::GetLastMouseDown() {
484   return NULL;
485 }
486
487 gfx::NativeView RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
488   return platform_view_->BuildInputMethodsGtkMenu();
489 }
490 #endif  // defined(TOOLKIT_GTK)
491
492 #if defined(OS_WIN)
493 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
494     gfx::NativeViewAccessible accessible_parent) {
495 }
496
497 gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
498     const {
499   return NULL;
500 }
501 #endif
502
503 void RenderWidgetHostViewGuest::DestroyGuestView() {
504   host_->SetView(NULL);
505   host_ = NULL;
506   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
507 }
508
509 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
510     ui::GestureConsumer* consumer) {
511   CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
512   return true;
513 }
514
515 void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent(
516     ui::GestureEvent* event) {
517   ForwardGestureEventToRenderer(event);
518 }
519
520 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
521     ui::TouchEvent* event) {
522   if (!host_)
523     return;
524
525   blink::WebTouchEvent cancel_event;
526   cancel_event.type = blink::WebInputEvent::TouchCancel;
527   cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
528   host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
529 }
530
531 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
532     ui::GestureEvent* gesture) {
533 #if defined(OS_WIN) || defined(USE_AURA)
534   if (!host_)
535     return false;
536
537   if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
538       gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
539       gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
540     return true;
541   }
542
543   blink::WebGestureEvent web_gesture =
544       MakeWebGestureEventFromUIEvent(*gesture);
545   const gfx::Point& client_point = gesture->location();
546   const gfx::Point& screen_point = gesture->location();
547
548   web_gesture.x = client_point.x();
549   web_gesture.y = client_point.y();
550   web_gesture.globalX = screen_point.x();
551   web_gesture.globalY = screen_point.y();
552
553   if (web_gesture.type == blink::WebGestureEvent::Undefined)
554     return false;
555   if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
556     host_->ForwardGestureEvent(
557         CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
558   }
559   host_->ForwardGestureEvent(web_gesture);
560   return true;
561 #else
562   return false;
563 #endif
564 }
565
566 void RenderWidgetHostViewGuest::ProcessGestures(
567     ui::GestureRecognizer::Gestures* gestures) {
568   if ((gestures == NULL) || gestures->empty())
569     return;
570   for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
571       g_it != gestures->end();
572       ++g_it) {
573     ForwardGestureEventToRenderer(*g_it);
574   }
575 }
576
577
578 }  // namespace content