[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / frame_host / render_widget_host_view_guest.cc
blob638a2327deb26072192ec44a55c992ee5fb2fa02
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 "cc/surfaces/surface.h"
10 #include "cc/surfaces/surface_factory.h"
11 #include "cc/surfaces/surface_manager.h"
12 #include "cc/surfaces/surface_sequence.h"
13 #include "content/browser/browser_plugin/browser_plugin_guest.h"
14 #include "content/browser/compositor/surface_utils.h"
15 #include "content/browser/frame_host/render_widget_host_view_guest.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/common/browser_plugin/browser_plugin_messages.h"
18 #include "content/common/frame_messages.h"
19 #include "content/common/gpu/gpu_messages.h"
20 #include "content/common/input/web_touch_event_traits.h"
21 #include "content/common/view_messages.h"
22 #include "content/common/webplugin_geometry.h"
23 #include "content/public/common/content_switches.h"
24 #include "skia/ext/platform_canvas.h"
25 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
27 #if defined(OS_MACOSX)
28 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
29 #endif
31 #if defined(USE_AURA)
32 #include "content/browser/renderer_host/ui_events_helper.h"
33 #endif
35 namespace content {
37 namespace {
39 #if defined(USE_AURA)
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::WebGestureDeviceTouchscreen;
45 return gesture_event;
47 #endif // defined(USE_AURA)
49 } // namespace
51 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
52 RenderWidgetHost* widget_host,
53 BrowserPluginGuest* guest,
54 base::WeakPtr<RenderWidgetHostViewBase> platform_view)
55 : RenderWidgetHostViewChildFrame(widget_host),
56 // |guest| is NULL during test.
57 guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
58 platform_view_(platform_view) {
59 #if defined(USE_AURA)
60 gesture_recognizer_.reset(ui::GestureRecognizer::Create());
61 gesture_recognizer_->AddGestureEventHelper(this);
62 #endif // defined(USE_AURA)
65 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
66 #if defined(USE_AURA)
67 gesture_recognizer_->RemoveGestureEventHelper(this);
68 #endif // defined(USE_AURA)
71 bool RenderWidgetHostViewGuest::OnMessageReceivedFromEmbedder(
72 const IPC::Message& message,
73 RenderWidgetHostImpl* embedder) {
74 bool handled = true;
75 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(RenderWidgetHostViewGuest, message,
76 embedder)
77 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
78 OnHandleInputEvent)
79 IPC_MESSAGE_UNHANDLED(handled = false)
80 IPC_END_MESSAGE_MAP()
81 return handled;
84 void RenderWidgetHostViewGuest::Show() {
85 // If the WebContents associated with us showed an interstitial page in the
86 // beginning, the teardown path might call WasShown() while |host_| is in
87 // the process of destruction. Avoid calling WasShown below in this case.
88 // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
89 // first place: http://crbug.com/273089.
91 // |guest_| is NULL during test.
92 if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
93 return;
94 // Make sure the size of this view matches the size of the WebContentsView.
95 // The two sizes may fall out of sync if we switch RenderWidgetHostViews,
96 // resize, and then switch page, as is the case with interstitial pages.
97 // NOTE: |guest_| is NULL in unit tests.
98 if (guest_)
99 SetSize(guest_->web_contents()->GetViewBounds().size());
100 host_->WasShown(ui::LatencyInfo());
103 void RenderWidgetHostViewGuest::Hide() {
104 // |guest_| is NULL during test.
105 if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
106 return;
107 host_->WasHidden();
110 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
111 size_ = size;
112 host_->WasResized();
115 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
116 SetSize(rect.size());
119 void RenderWidgetHostViewGuest::Focus() {
120 // InterstitialPageImpl focuses views directly, so we place focus logic here.
121 // InterstitialPages are not WebContents, and so BrowserPluginGuest does not
122 // have direct access to the interstitial page's RenderWidgetHost.
123 if (guest_)
124 guest_->SetFocus(host_, true, blink::WebFocusTypeNone);
127 bool RenderWidgetHostViewGuest::HasFocus() const {
128 if (!guest_)
129 return false;
130 return guest_->focused();
133 #if defined(USE_AURA)
134 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
135 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
136 // TODO(fsamuel): Currently we will only take this codepath if the guest has
137 // requested touch events. A better solution is to always forward touchpresses
138 // to the embedder process to target a BrowserPlugin, and then route all
139 // subsequent touch points of that touchdown to the appropriate guest until
140 // that touch point is released.
141 ScopedVector<ui::TouchEvent> events;
142 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
143 return;
145 ui::EventResult result = (ack_result ==
146 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
147 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
148 end = events.end(); iter != end; ++iter) {
149 if (!gesture_recognizer_->ProcessTouchEventPreDispatch(*iter, this))
150 continue;
152 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
153 gestures.reset(gesture_recognizer_->AckTouchEvent(
154 (*iter)->unique_event_id(), result, this));
155 ProcessGestures(gestures.get());
158 #endif
160 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
161 if (!guest_)
162 return gfx::Rect();
164 RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
165 gfx::Rect embedder_bounds;
166 if (rwhv)
167 embedder_bounds = rwhv->GetViewBounds();
168 return gfx::Rect(
169 guest_->GetScreenCoordinates(embedder_bounds.origin()), size_);
172 void RenderWidgetHostViewGuest::RenderProcessGone(
173 base::TerminationStatus status,
174 int error_code) {
175 // The |platform_view_| gets destroyed before we get here if this view
176 // is for an InterstitialPage.
177 if (platform_view_)
178 platform_view_->RenderProcessGone(status, error_code);
180 // Destroy the guest view instance only, so we don't end up calling
181 // platform_view_->Destroy().
182 DestroyGuestView();
185 void RenderWidgetHostViewGuest::Destroy() {
186 // The RenderWidgetHost's destruction led here, so don't call it.
187 DestroyGuestView();
189 if (platform_view_) // The platform view might have been destroyed already.
190 platform_view_->Destroy();
193 gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
194 return RenderWidgetHostViewBase::GetPhysicalBackingSize();
197 base::string16 RenderWidgetHostViewGuest::GetSelectedText() const {
198 return platform_view_->GetSelectedText();
201 void RenderWidgetHostViewGuest::SetTooltipText(
202 const base::string16& tooltip_text) {
203 if (guest_)
204 guest_->SetTooltipText(tooltip_text);
207 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
208 uint32 output_surface_id,
209 scoped_ptr<cc::CompositorFrame> frame) {
210 if (!guest_ || !guest_->attached()) {
211 // We shouldn't hang on to a surface while we are detached.
212 ClearCompositorSurfaceIfNecessary();
213 return;
216 last_scroll_offset_ = frame->metadata.root_scroll_offset;
217 // When not using surfaces, the frame just gets proxied to
218 // the embedder's renderer to be composited.
219 if (!frame->delegated_frame_data || !use_surfaces_) {
220 guest_->SwapCompositorFrame(output_surface_id,
221 host_->GetProcess()->GetID(),
222 host_->GetRoutingID(),
223 frame.Pass());
224 return;
227 cc::RenderPass* root_pass =
228 frame->delegated_frame_data->render_pass_list.back();
230 gfx::Size frame_size = root_pass->output_rect.size();
231 float scale_factor = frame->metadata.device_scale_factor;
233 // Check whether we need to recreate the cc::Surface, which means the child
234 // frame renderer has changed its output surface, or size, or scale factor.
235 if (output_surface_id != last_output_surface_id_ && surface_factory_) {
236 surface_factory_->Destroy(surface_id_);
237 surface_factory_.reset();
239 if (output_surface_id != last_output_surface_id_ ||
240 frame_size != current_surface_size_ ||
241 scale_factor != current_surface_scale_factor_ ||
242 guest_->has_attached_since_surface_set()) {
243 ClearCompositorSurfaceIfNecessary();
244 last_output_surface_id_ = output_surface_id;
245 current_surface_size_ = frame_size;
246 current_surface_scale_factor_ = scale_factor;
249 if (!surface_factory_) {
250 cc::SurfaceManager* manager = GetSurfaceManager();
251 surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
254 if (surface_id_.is_null()) {
255 surface_id_ = id_allocator_->GenerateId();
256 surface_factory_->Create(surface_id_);
258 cc::SurfaceSequence sequence = cc::SurfaceSequence(
259 id_allocator_->id_namespace(), next_surface_sequence_++);
260 // The renderer process will satisfy this dependency when it creates a
261 // SurfaceLayer.
262 cc::SurfaceManager* manager = GetSurfaceManager();
263 manager->GetSurfaceForId(surface_id_)->AddDestructionDependency(sequence);
264 guest_->SetChildFrameSurface(surface_id_, frame_size, scale_factor,
265 sequence);
268 cc::SurfaceFactory::DrawCallback ack_callback = base::Bind(
269 &RenderWidgetHostViewChildFrame::SurfaceDrawn,
270 RenderWidgetHostViewChildFrame::AsWeakPtr(), output_surface_id);
271 ack_pending_count_++;
272 // If this value grows very large, something is going wrong.
273 DCHECK(ack_pending_count_ < 1000);
274 surface_factory_->SubmitCompositorFrame(surface_id_, frame.Pass(),
275 ack_callback);
278 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
279 if (!platform_view_) {
280 // In theory, we can get here if there's a delay between DestroyGuestView()
281 // being called and when our destructor is invoked.
282 return false;
285 return platform_view_->OnMessageReceived(msg);
288 void RenderWidgetHostViewGuest::InitAsChild(
289 gfx::NativeView parent_view) {
290 platform_view_->InitAsChild(parent_view);
293 void RenderWidgetHostViewGuest::InitAsPopup(
294 RenderWidgetHostView* parent_host_view, const gfx::Rect& bounds) {
295 // This should never get called.
296 NOTREACHED();
299 void RenderWidgetHostViewGuest::InitAsFullscreen(
300 RenderWidgetHostView* reference_host_view) {
301 // This should never get called.
302 NOTREACHED();
305 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
306 if (!guest_)
307 return gfx::NativeView();
309 RenderWidgetHostView* rwhv = guest_->GetOwnerRenderWidgetHostView();
310 if (!rwhv)
311 return gfx::NativeView();
312 return rwhv->GetNativeView();
315 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
316 if (!guest_)
317 return static_cast<gfx::NativeViewId>(NULL);
319 RenderWidgetHostView* rwhv = guest_->GetOwnerRenderWidgetHostView();
320 if (!rwhv)
321 return static_cast<gfx::NativeViewId>(NULL);
322 return rwhv->GetNativeViewId();
325 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
326 if (!guest_)
327 return gfx::NativeViewAccessible();
329 RenderWidgetHostView* rwhv = guest_->GetOwnerRenderWidgetHostView();
330 if (!rwhv)
331 return gfx::NativeViewAccessible();
332 return rwhv->GetNativeViewAccessible();
335 void RenderWidgetHostViewGuest::MovePluginWindows(
336 const std::vector<WebPluginGeometry>& moves) {
337 platform_view_->MovePluginWindows(moves);
340 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
341 // InterstitialPages are not WebContents so we cannot intercept
342 // ViewHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
343 // All guest RenderViewHosts have RenderWidgetHostViewGuests however,
344 // and so we will always hit this code path.
345 if (!guest_)
346 return;
347 guest_->SendMessageToEmbedder(
348 new BrowserPluginMsg_SetCursor(guest_->browser_plugin_instance_id(),
349 cursor));
353 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
354 platform_view_->SetIsLoading(is_loading);
357 void RenderWidgetHostViewGuest::TextInputStateChanged(
358 const ViewHostMsg_TextInputState_Params& params) {
359 if (!guest_)
360 return;
362 RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
363 if (!rwhv)
364 return;
365 // Forward the information to embedding RWHV.
366 rwhv->TextInputStateChanged(params);
369 void RenderWidgetHostViewGuest::ImeCancelComposition() {
370 if (!guest_)
371 return;
373 RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
374 if (!rwhv)
375 return;
376 // Forward the information to embedding RWHV.
377 rwhv->ImeCancelComposition();
380 #if defined(OS_MACOSX) || defined(USE_AURA)
381 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
382 const gfx::Range& range,
383 const std::vector<gfx::Rect>& character_bounds) {
384 if (!guest_)
385 return;
387 RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
388 if (!rwhv)
389 return;
390 std::vector<gfx::Rect> guest_character_bounds;
391 for (size_t i = 0; i < character_bounds.size(); ++i) {
392 guest_character_bounds.push_back(gfx::Rect(
393 guest_->GetScreenCoordinates(character_bounds[i].origin()),
394 character_bounds[i].size()));
396 // Forward the information to embedding RWHV.
397 rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
399 #endif
401 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
402 size_t offset,
403 const gfx::Range& range) {
404 platform_view_->SelectionChanged(text, offset, range);
407 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
408 const ViewHostMsg_SelectionBounds_Params& params) {
409 if (!guest_)
410 return;
412 RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
413 if (!rwhv)
414 return;
415 ViewHostMsg_SelectionBounds_Params guest_params(params);
416 guest_params.anchor_rect.set_origin(
417 guest_->GetScreenCoordinates(params.anchor_rect.origin()));
418 guest_params.focus_rect.set_origin(
419 guest_->GetScreenCoordinates(params.focus_rect.origin()));
420 rwhv->SelectionBoundsChanged(guest_params);
423 void RenderWidgetHostViewGuest::SetBackgroundColor(SkColor color) {
424 // Content embedders can toggle opaque backgrounds through this API.
425 // We plumb the value here so that BrowserPlugin updates its compositing
426 // state in response to this change. We also want to preserve this flag
427 // after recovering from a crash so we let BrowserPluginGuest store it.
428 if (!guest_)
429 return;
430 RenderWidgetHostViewBase::SetBackgroundColor(color);
431 bool opaque = GetBackgroundOpaque();
432 host_->SetBackgroundOpaque(opaque);
433 guest_->SetContentsOpaque(opaque);
436 bool RenderWidgetHostViewGuest::LockMouse() {
437 return platform_view_->LockMouse();
440 void RenderWidgetHostViewGuest::UnlockMouse() {
441 return platform_view_->UnlockMouse();
444 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
445 if (!guest_)
446 return;
447 RenderWidgetHostViewBase* embedder_view = GetOwnerRenderWidgetHostView();
448 if (embedder_view)
449 embedder_view->GetScreenInfo(results);
452 bool RenderWidgetHostViewGuest::GetScreenColorProfile(
453 std::vector<char>* color_profile) {
454 if (!guest_)
455 return false;
456 DCHECK(color_profile->empty());
457 RenderWidgetHostViewBase* embedder_view = GetOwnerRenderWidgetHostView();
458 if (embedder_view)
459 return embedder_view->GetScreenColorProfile(color_profile);
460 return false;
463 #if defined(OS_MACOSX)
464 void RenderWidgetHostViewGuest::SetActive(bool active) {
465 platform_view_->SetActive(active);
468 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
469 platform_view_->SetWindowVisibility(visible);
472 void RenderWidgetHostViewGuest::WindowFrameChanged() {
473 platform_view_->WindowFrameChanged();
476 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
477 if (!guest_)
478 return;
480 gfx::Point origin;
481 gfx::Rect guest_bounds = GetViewBounds();
482 RenderWidgetHostView* rwhv = guest_->GetOwnerRenderWidgetHostView();
483 gfx::Rect embedder_bounds;
484 if (rwhv)
485 embedder_bounds = rwhv->GetViewBounds();
487 gfx::Vector2d guest_offset = gfx::Vector2d(
488 // Horizontal offset of guest from embedder.
489 guest_bounds.x() - embedder_bounds.x(),
490 // Vertical offset from guest's top to embedder's bottom edge.
491 embedder_bounds.bottom() - guest_bounds.y());
493 RenderWidgetHostViewMacDictionaryHelper helper(platform_view_.get());
494 helper.SetTargetView(rwhv);
495 helper.set_offset(guest_offset);
496 helper.ShowDefinitionForSelection();
499 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
500 return platform_view_->SupportsSpeech();
503 void RenderWidgetHostViewGuest::SpeakSelection() {
504 platform_view_->SpeakSelection();
507 bool RenderWidgetHostViewGuest::IsSpeaking() const {
508 return platform_view_->IsSpeaking();
511 void RenderWidgetHostViewGuest::StopSpeaking() {
512 platform_view_->StopSpeaking();
515 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
516 const NativeWebKeyboardEvent& event) {
517 return false;
520 #endif // defined(OS_MACOSX)
522 #if defined(OS_ANDROID) || defined(USE_AURA)
523 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
524 const gfx::Rect& rect_pixels,
525 const SkBitmap& zoomed_bitmap) {
527 #endif // defined(OS_ANDROID) || defined(USE_AURA)
529 #if defined(OS_ANDROID)
530 void RenderWidgetHostViewGuest::LockCompositingSurface() {
533 void RenderWidgetHostViewGuest::UnlockCompositingSurface() {
535 #endif // defined(OS_ANDROID)
537 #if defined(OS_WIN)
538 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
539 gfx::NativeViewAccessible accessible_parent) {
542 gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
543 const {
544 return NULL;
546 #endif
548 void RenderWidgetHostViewGuest::DestroyGuestView() {
549 host_->SetView(NULL);
550 host_ = NULL;
551 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
554 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
555 ui::GestureConsumer* consumer) {
556 CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
557 return true;
560 void RenderWidgetHostViewGuest::DispatchGestureEvent(
561 ui::GestureEvent* event) {
562 ForwardGestureEventToRenderer(event);
565 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
566 ui::TouchEvent* event) {
567 if (!host_)
568 return;
570 blink::WebTouchEvent cancel_event;
571 // TODO(rbyers): This event has no touches in it. Don't we need to know what
572 // touches are currently active in order to cancel them all properly?
573 WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel,
574 event->time_stamp().InSecondsF(),
575 &cancel_event);
577 host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
580 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
581 ui::GestureEvent* gesture) {
582 #if defined(USE_AURA)
583 if (!host_)
584 return false;
586 if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
587 gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
588 gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
589 return true;
592 blink::WebGestureEvent web_gesture =
593 MakeWebGestureEventFromUIEvent(*gesture);
594 const gfx::Point& client_point = gesture->location();
595 const gfx::Point& screen_point = gesture->location();
597 web_gesture.x = client_point.x();
598 web_gesture.y = client_point.y();
599 web_gesture.globalX = screen_point.x();
600 web_gesture.globalY = screen_point.y();
602 if (web_gesture.type == blink::WebGestureEvent::Undefined)
603 return false;
604 if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
605 host_->ForwardGestureEvent(
606 CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
608 host_->ForwardGestureEvent(web_gesture);
609 return true;
610 #else
611 return false;
612 #endif
615 void RenderWidgetHostViewGuest::ProcessGestures(
616 ui::GestureRecognizer::Gestures* gestures) {
617 if ((gestures == NULL) || gestures->empty())
618 return;
619 for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
620 g_it != gestures->end();
621 ++g_it) {
622 ForwardGestureEventToRenderer(*g_it);
626 RenderWidgetHostViewBase*
627 RenderWidgetHostViewGuest::GetOwnerRenderWidgetHostView() const {
628 return static_cast<RenderWidgetHostViewBase*>(
629 guest_->GetOwnerRenderWidgetHostView());
632 void RenderWidgetHostViewGuest::OnHandleInputEvent(
633 RenderWidgetHostImpl* embedder,
634 int browser_plugin_instance_id,
635 const gfx::Rect& guest_window_rect,
636 const blink::WebInputEvent* event) {
637 if (blink::WebInputEvent::isMouseEventType(event->type)) {
638 // The mouse events for BrowserPlugin are modified by all
639 // the CSS transforms applied on the <object> and embedder. As a result of
640 // this, the coordinates passed on to the guest renderer are potentially
641 // incorrect to determine the position of the context menu(they are not the
642 // actual X, Y of the window). As a hack, we report the last location of a
643 // right mouse up to the BrowserPluginGuest to inform it of the next
644 // potential location for context menu (BUG=470087).
645 // TODO(ekaramad): Find a better and more fundamental solution. Could the
646 // ContextMenuParams be based on global X, Y?
647 const blink::WebMouseEvent& mouse_event =
648 static_cast<const blink::WebMouseEvent&>(*event);
649 // A MouseDown on the ButtonRight could suggest a ContextMenu.
650 if (guest_ && mouse_event.type == blink::WebInputEvent::MouseDown &&
651 mouse_event.button == blink::WebPointerProperties::ButtonRight)
652 guest_->SetContextMenuPosition(
653 gfx::Point(mouse_event.globalX - GetViewBounds().x(),
654 mouse_event.globalY - GetViewBounds().y()));
655 host_->ForwardMouseEvent(mouse_event);
656 return;
659 if (event->type == blink::WebInputEvent::MouseWheel) {
660 host_->ForwardWheelEvent(
661 *static_cast<const blink::WebMouseWheelEvent*>(event));
662 return;
665 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
666 if (!embedder->GetLastKeyboardEvent())
667 return;
668 NativeWebKeyboardEvent keyboard_event(*embedder->GetLastKeyboardEvent());
669 host_->ForwardKeyboardEvent(keyboard_event);
670 return;
673 if (blink::WebInputEvent::isTouchEventType(event->type)) {
674 if (event->type == blink::WebInputEvent::TouchStart &&
675 !embedder->GetView()->HasFocus()) {
676 embedder->GetView()->Focus();
679 host_->ForwardTouchEventWithLatencyInfo(
680 *static_cast<const blink::WebTouchEvent*>(event),
681 ui::LatencyInfo());
682 return;
685 if (blink::WebInputEvent::isGestureEventType(event->type)) {
686 host_->ForwardGestureEvent(
687 *static_cast<const blink::WebGestureEvent*>(event));
688 return;
692 } // namespace content