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 "content/browser/browser_plugin/browser_plugin_guest.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/frame_host/render_frame_host_impl.h"
15 #include "content/browser/frame_host/render_widget_host_view_guest.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_view_base.h"
20 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/browser/web_contents/web_contents_view_guest.h"
22 #include "content/common/browser_plugin/browser_plugin_messages.h"
23 #include "content/common/content_constants_internal.h"
24 #include "content/common/drag_messages.h"
25 #include "content/common/input_messages.h"
26 #include "content/common/view_messages.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_plugin_guest_manager.h"
29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/render_widget_host_view.h"
31 #include "content/public/browser/user_metrics.h"
32 #include "content/public/browser/web_contents_observer.h"
33 #include "content/public/common/drop_data.h"
34 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
36 #if defined(OS_MACOSX)
37 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
42 class BrowserPluginGuest::EmbedderWebContentsObserver
43 : public WebContentsObserver {
45 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
46 : WebContentsObserver(guest->embedder_web_contents()),
47 browser_plugin_guest_(guest) {
50 virtual ~EmbedderWebContentsObserver() {
53 // WebContentsObserver implementation.
54 virtual void WasShown() OVERRIDE {
55 browser_plugin_guest_->EmbedderVisibilityChanged(true);
58 virtual void WasHidden() OVERRIDE {
59 browser_plugin_guest_->EmbedderVisibilityChanged(false);
63 BrowserPluginGuest* browser_plugin_guest_;
65 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
68 BrowserPluginGuest::BrowserPluginGuest(
71 WebContentsImpl* web_contents,
72 BrowserPluginGuestDelegate* delegate)
73 : WebContentsObserver(web_contents),
74 embedder_web_contents_(NULL),
75 instance_id_(instance_id),
76 guest_device_scale_factor_(1.0f),
79 pending_lock_request_(false),
80 guest_visible_(false),
82 embedder_visible_(true),
84 has_render_view_(has_render_view),
85 is_in_destruction_(false),
86 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
87 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
88 last_can_compose_inline_(true),
90 weak_ptr_factory_(this) {
93 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
94 web_contents->SetBrowserPluginGuest(this);
95 delegate->RegisterDestructionCallback(
96 base::Bind(&BrowserPluginGuest::WillDestroy, AsWeakPtr()));
99 void BrowserPluginGuest::WillDestroy() {
100 is_in_destruction_ = true;
101 embedder_web_contents_ = NULL;
104 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
105 return weak_ptr_factory_.GetWeakPtr();
108 bool BrowserPluginGuest::LockMouse(bool allowed) {
109 if (!attached() || (mouse_locked_ == allowed))
112 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
115 void BrowserPluginGuest::Destroy() {
116 delegate_->Destroy();
119 WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow(
120 const WebContents::CreateParams& params) {
121 WebContentsImpl* new_contents =
122 static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params));
123 DCHECK(new_contents);
127 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
128 const IPC::Message& message) {
130 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
131 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
132 OnCompositorFrameSwappedACK)
133 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
134 OnCopyFromCompositingSurfaceAck)
135 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
137 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
138 OnExecuteEditCommand)
139 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
140 OnExtendSelectionAndDelete)
141 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
143 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
144 OnImeConfirmComposition)
145 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
147 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
148 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
149 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
150 OnReclaimCompositorResources)
151 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
152 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
153 OnSetEditCommandsForNextKeyEvent)
154 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
155 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
157 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
158 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
159 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
160 IPC_MESSAGE_UNHANDLED(handled = false)
161 IPC_END_MESSAGE_MAP()
165 void BrowserPluginGuest::Initialize(
166 const BrowserPluginHostMsg_Attach_Params& params,
167 WebContentsImpl* embedder_web_contents,
168 const base::DictionaryValue& extra_params) {
169 focused_ = params.focused;
170 guest_visible_ = params.visible;
171 guest_opaque_ = params.opaque;
172 guest_window_rect_ = gfx::Rect(params.origin,
173 params.resize_guest_params.view_size);
175 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
177 embedder_web_contents_ = embedder_web_contents;
179 WebContentsViewGuest* new_view =
180 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
181 new_view->OnGuestInitialized(embedder_web_contents->GetView());
183 RendererPreferences* renderer_prefs =
184 GetWebContents()->GetMutableRendererPrefs();
185 std::string guest_user_agent_override = renderer_prefs->user_agent_override;
186 // Copy renderer preferences (and nothing else) from the embedder's
187 // WebContents to the guest.
189 // For GTK and Aura this is necessary to get proper renderer configuration
190 // values for caret blinking interval, colors related to selection and
192 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
193 renderer_prefs->user_agent_override = guest_user_agent_override;
195 // We would like the guest to report changes to frame names so that we can
196 // update the BrowserPlugin's corresponding 'name' attribute.
197 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
198 renderer_prefs->report_frame_name_changes = true;
199 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
200 // navigations still continue to function inside the app.
201 renderer_prefs->browser_handles_all_top_level_requests = false;
202 // Disable "client blocked" error page for browser plugin.
203 renderer_prefs->disable_client_blocked_error_page = true;
205 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
207 OnResizeGuest(instance_id_, params.resize_guest_params);
209 // Create a swapped out RenderView for the guest in the embedder render
210 // process, so that the embedder can access the guest's window object.
211 int guest_routing_id =
212 GetWebContents()->CreateSwappedOutRenderView(
213 embedder_web_contents_->GetSiteInstance());
214 SendMessageToEmbedder(
215 new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
218 // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
219 // be reset again the next time preferences are updated.
220 WebPreferences prefs =
221 GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
222 prefs.navigate_on_drag_drop = false;
223 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
225 // Enable input method for guest if it's enabled for the embedder.
226 if (static_cast<RenderViewHostImpl*>(
227 embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
228 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
229 GetWebContents()->GetRenderViewHost());
230 guest_rvh->SetInputMethodActive(true);
233 // Inform the embedder of the guest's attachment.
234 SendMessageToEmbedder(new BrowserPluginMsg_Attach_ACK(instance_id_));
237 BrowserPluginGuest::~BrowserPluginGuest() {
241 BrowserPluginGuest* BrowserPluginGuest::Create(
243 WebContentsImpl* web_contents,
244 BrowserPluginGuestDelegate* delegate) {
245 return new BrowserPluginGuest(
246 instance_id, web_contents->opener() != NULL, web_contents, delegate);
250 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
251 return web_contents && web_contents->GetBrowserPluginGuest();
255 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
256 return render_view_host && IsGuest(
257 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
261 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
264 return embedder_web_contents_->GetRenderWidgetHostView();
267 void BrowserPluginGuest::UpdateVisibility() {
268 OnSetVisibility(instance_id_, visible());
271 void BrowserPluginGuest::CopyFromCompositingSurface(
272 gfx::Rect src_subrect,
274 const base::Callback<void(bool, const SkBitmap&)>& callback) {
275 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
276 SendMessageToEmbedder(
277 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
278 copy_request_id_, src_subrect, dst_size));
281 BrowserPluginGuestManager*
282 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
283 return GetWebContents()->GetBrowserContext()->GetGuestManager();
287 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
288 gfx::Rect guest_rect(bounds);
289 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
290 if (embedder_web_contents()->GetBrowserPluginGuest()) {
291 BrowserPluginGuest* embedder_guest =
292 embedder_web_contents()->GetBrowserPluginGuest();
293 guest_rect.Offset(embedder_guest->guest_window_rect_.OffsetFromOrigin());
298 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
299 embedder_visible_ = visible;
303 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
304 SendMessageToEmbedder(
305 new BrowserPluginMsg_SetMouseLock(instance_id(), allow));
308 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
309 return static_cast<WebContentsImpl*>(web_contents());
312 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
313 const gfx::Point& relative_position) const {
315 return relative_position;
317 gfx::Point screen_pos(relative_position);
318 screen_pos += guest_window_rect_.OffsetFromOrigin();
319 if (embedder_web_contents()->GetBrowserPluginGuest()) {
320 BrowserPluginGuest* embedder_guest =
321 embedder_web_contents()->GetBrowserPluginGuest();
322 screen_pos += embedder_guest->guest_window_rect_.OffsetFromOrigin();
327 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
329 // Some pages such as data URLs, javascript URLs, and about:blank
330 // do not load external resources and so they load prior to attachment.
331 // As a result, we must save all these IPCs until attachment and then
332 // forward them so that the embedder gets a chance to see and process
334 pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
337 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
338 embedder_web_contents_->Send(msg);
341 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
342 int screen_x, int screen_y, blink::WebDragOperation operation) {
343 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
344 screen_x, screen_y, operation);
347 void BrowserPluginGuest::EndSystemDrag() {
348 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
349 GetWebContents()->GetRenderViewHost());
350 guest_rvh->DragSourceSystemDragEnded();
353 void BrowserPluginGuest::SendQueuedMessages() {
357 while (!pending_messages_.empty()) {
358 linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
359 pending_messages_.pop_front();
360 SendMessageToEmbedder(message_ptr.release());
364 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
365 RenderFrameHost* render_frame_host,
367 PageTransition transition_type) {
368 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
371 void BrowserPluginGuest::RenderViewReady() {
372 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
373 // TODO(fsamuel): Investigate whether it's possible to update state earlier
374 // here (see http://crbug.com/158151).
375 Send(new InputMsg_SetFocus(routing_id(), focused_));
378 OnSetContentsOpaque(instance_id_, guest_opaque_);
380 RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
381 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
384 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
385 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
387 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
388 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
390 case base::TERMINATION_STATUS_PROCESS_CRASHED:
391 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
393 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
395 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
403 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
404 const IPC::Message& message) {
405 switch (message.type()) {
406 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
407 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
408 case BrowserPluginHostMsg_DragStatusUpdate::ID:
409 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
410 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
411 case BrowserPluginHostMsg_HandleInputEvent::ID:
412 case BrowserPluginHostMsg_ImeConfirmComposition::ID:
413 case BrowserPluginHostMsg_ImeSetComposition::ID:
414 case BrowserPluginHostMsg_LockMouse_ACK::ID:
415 case BrowserPluginHostMsg_PluginDestroyed::ID:
416 case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
417 case BrowserPluginHostMsg_ResizeGuest::ID:
418 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
419 case BrowserPluginHostMsg_SetFocus::ID:
420 case BrowserPluginHostMsg_SetContentsOpaque::ID:
421 case BrowserPluginHostMsg_SetVisibility::ID:
422 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
423 case BrowserPluginHostMsg_UpdateGeometry::ID:
430 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
432 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
433 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
434 OnImeCancelComposition)
435 #if defined(OS_MACOSX) || defined(USE_AURA)
436 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
437 OnImeCompositionRangeChanged)
439 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
440 OnHasTouchEventHandlers)
441 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
442 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
443 #if defined(OS_MACOSX)
444 // MacOSX creates and populates platform-specific select drop-down menus
445 // whereas other platforms merely create a popup window that the guest
446 // renderer process paints inside.
447 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
449 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
450 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
451 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
452 OnTextInputStateChanged)
453 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
455 IPC_MESSAGE_UNHANDLED(handled = false)
456 IPC_END_MESSAGE_MAP()
460 void BrowserPluginGuest::Attach(
461 WebContentsImpl* embedder_web_contents,
462 const BrowserPluginHostMsg_Attach_Params& params,
463 const base::DictionaryValue& extra_params) {
468 delegate_->WillAttach(embedder_web_contents, extra_params);
470 // If a RenderView has already been created for this new window, then we need
471 // to initialize the browser-side state now so that the RenderFrameHostManager
472 // does not create a new RenderView on navigation.
473 if (has_render_view_) {
474 static_cast<RenderViewHostImpl*>(
475 GetWebContents()->GetRenderViewHost())->Init();
476 WebContentsViewGuest* new_view =
477 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
478 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
481 Initialize(params, embedder_web_contents, extra_params);
483 SendQueuedMessages();
486 delegate_->DidAttach();
488 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
491 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
493 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
494 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
495 params.output_surface_id,
496 params.producing_host_id,
500 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
501 blink::WebDragStatus drag_status,
502 const DropData& drop_data,
503 blink::WebDragOperationsMask mask,
504 const gfx::Point& location) {
505 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
506 switch (drag_status) {
507 case blink::WebDragStatusEnter:
508 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
510 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
512 case blink::WebDragStatusOver:
513 host->DragTargetDragOver(location, location, mask, 0);
515 case blink::WebDragStatusLeave:
516 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
517 host->DragTargetDragLeave();
519 case blink::WebDragStatusDrop:
520 host->DragTargetDrop(location, location, 0);
523 case blink::WebDragStatusUnknown:
528 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
529 const std::string& name) {
530 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
533 void BrowserPluginGuest::OnImeSetComposition(
535 const std::string& text,
536 const std::vector<blink::WebCompositionUnderline>& underlines,
539 Send(new InputMsg_ImeSetComposition(routing_id(),
540 base::UTF8ToUTF16(text), underlines,
541 selection_start, selection_end));
544 void BrowserPluginGuest::OnImeConfirmComposition(
546 const std::string& text,
547 bool keep_selection) {
548 Send(new InputMsg_ImeConfirmComposition(routing_id(),
549 base::UTF8ToUTF16(text),
550 gfx::Range::InvalidRange(),
554 void BrowserPluginGuest::OnExtendSelectionAndDelete(
558 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
559 web_contents()->GetFocusedFrame());
561 rfh->ExtendSelectionAndDelete(before, after);
564 void BrowserPluginGuest::OnReclaimCompositorResources(
566 const FrameHostMsg_ReclaimCompositorResources_Params& params) {
567 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
568 params.output_surface_id,
569 params.renderer_host_id,
573 void BrowserPluginGuest::OnHandleInputEvent(
575 const gfx::Rect& guest_window_rect,
576 const blink::WebInputEvent* event) {
577 guest_window_rect_ = guest_window_rect;
578 // If the embedder's RWHV is destroyed then that means that the embedder's
579 // window has been closed but the embedder's WebContents has not yet been
580 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
581 // if there is a visible embedder.
582 if (embedder_web_contents_->GetRenderWidgetHostView()) {
583 guest_screen_rect_ = guest_window_rect;
584 guest_screen_rect_.Offset(
585 embedder_web_contents_->GetRenderWidgetHostView()->
586 GetViewBounds().OffsetFromOrigin());
588 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
589 GetWebContents()->GetRenderViewHost());
591 if (blink::WebInputEvent::isMouseEventType(event->type)) {
592 guest_rvh->ForwardMouseEvent(
593 *static_cast<const blink::WebMouseEvent*>(event));
597 if (event->type == blink::WebInputEvent::MouseWheel) {
598 guest_rvh->ForwardWheelEvent(
599 *static_cast<const blink::WebMouseWheelEvent*>(event));
603 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
604 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
605 embedder_web_contents_->GetRenderViewHost());
606 if (!embedder_rvh->GetLastKeyboardEvent())
608 NativeWebKeyboardEvent keyboard_event(
609 *embedder_rvh->GetLastKeyboardEvent());
610 guest_rvh->ForwardKeyboardEvent(keyboard_event);
614 if (blink::WebInputEvent::isTouchEventType(event->type)) {
615 guest_rvh->ForwardTouchEventWithLatencyInfo(
616 *static_cast<const blink::WebTouchEvent*>(event),
621 if (blink::WebInputEvent::isGestureEventType(event->type)) {
622 guest_rvh->ForwardGestureEvent(
623 *static_cast<const blink::WebGestureEvent*>(event));
628 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
629 bool last_unlocked_by_target,
631 if (pending_lock_request_) {
632 // Immediately reject the lock because only one pointerLock may be active
634 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
638 pending_lock_request_ = true;
640 delegate_->RequestPointerLockPermission(
642 last_unlocked_by_target,
643 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
644 weak_ptr_factory_.GetWeakPtr()));
647 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
648 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
649 pending_lock_request_ = false;
651 mouse_locked_ = true;
654 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
658 void BrowserPluginGuest::OnResizeGuest(
660 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
661 if (!params.size_changed)
663 // BrowserPlugin manages resize flow control itself and does not depend
664 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
665 // here. If we are setting the size for the first time before navigating then
666 // BrowserPluginGuest does not yet have a RenderViewHost.
667 if (GetWebContents()->GetRenderViewHost()) {
668 RenderWidgetHostImpl* render_widget_host =
669 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
670 render_widget_host->ResetSizeAndRepaintPendingFlags();
672 if (guest_device_scale_factor_ != params.scale_factor) {
673 guest_device_scale_factor_ = params.scale_factor;
674 render_widget_host->NotifyScreenInfoChanged();
678 if (last_seen_browser_plugin_size_ != params.view_size) {
679 delegate_->ElementSizeChanged(last_seen_browser_plugin_size_,
681 last_seen_browser_plugin_size_ = params.view_size;
684 // Just resize the WebContents and repaint if needed.
685 if (!params.view_size.IsEmpty())
686 GetWebContents()->GetView()->SizeContents(params.view_size);
688 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
691 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
693 Send(new InputMsg_SetFocus(routing_id(), focused));
694 if (!focused && mouse_locked_)
697 // Restore the last seen state of text input to the view.
698 RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
699 web_contents()->GetRenderWidgetHostView());
701 ViewHostMsg_TextInputState_Params params;
702 params.type = last_text_input_type_;
703 params.mode = last_input_mode_;
704 params.can_compose_inline = last_can_compose_inline_;
705 rwhv->TextInputStateChanged(params);
709 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
711 const std::vector<EditCommand>& edit_commands) {
712 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
716 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
717 guest_opaque_ = opaque;
718 Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
721 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
722 guest_visible_ = visible;
723 if (embedder_visible_ && guest_visible_)
724 GetWebContents()->WasShown();
726 GetWebContents()->WasHidden();
729 void BrowserPluginGuest::OnUnlockMouse() {
730 SendMessageToEmbedder(
731 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
734 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
735 // mouse_locked_ could be false here if the lock attempt was cancelled due
736 // to window focus, or for various other reasons before the guest was informed
737 // of the lock's success.
739 Send(new ViewMsg_MouseLockLost(routing_id()));
740 mouse_locked_ = false;
743 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
746 const SkBitmap& bitmap) {
747 CHECK(copy_request_callbacks_.count(request_id));
748 if (!copy_request_callbacks_.count(request_id))
750 const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
751 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
752 copy_request_callbacks_.erase(request_id);
755 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
756 const gfx::Rect& view_rect) {
757 // The plugin has moved within the embedder without resizing or the
758 // embedder/container's view rect changing.
759 guest_window_rect_ = view_rect;
760 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
761 GetWebContents()->GetRenderViewHost());
763 rvh->SendScreenRects();
766 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
767 SendMessageToEmbedder(
768 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
771 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
772 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
775 #if defined(OS_MACOSX)
776 void BrowserPluginGuest::OnShowPopup(
777 const ViewHostMsg_ShowPopup_Params& params) {
778 gfx::Rect translated_bounds(params.bounds);
779 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
780 BrowserPluginPopupMenuHelper popup_menu_helper(
781 embedder_web_contents_->GetRenderViewHost(),
782 GetWebContents()->GetRenderViewHost());
783 popup_menu_helper.ShowPopupMenu(translated_bounds,
785 params.item_font_size,
786 params.selected_item,
788 params.right_aligned,
789 params.allow_multiple_selection);
793 void BrowserPluginGuest::OnShowWidget(int route_id,
794 const gfx::Rect& initial_pos) {
795 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
798 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
799 SendMessageToEmbedder(
800 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
803 void BrowserPluginGuest::OnUpdateRect(
804 const ViewHostMsg_UpdateRect_Params& params) {
805 BrowserPluginMsg_UpdateRect_Params relay_params;
806 relay_params.view_size = params.view_size;
807 relay_params.scale_factor = params.scale_factor;
808 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
811 if (last_seen_view_size_ != params.view_size) {
812 delegate_->GuestSizeChanged(last_seen_view_size_, params.view_size);
813 last_seen_view_size_ = params.view_size;
816 SendMessageToEmbedder(
817 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
820 void BrowserPluginGuest::OnTextInputStateChanged(
821 const ViewHostMsg_TextInputState_Params& params) {
822 // Save the state of text input so we can restore it on focus.
823 last_text_input_type_ = params.type;
824 last_input_mode_ = params.mode;
825 last_can_compose_inline_ = params.can_compose_inline;
827 static_cast<RenderWidgetHostViewBase*>(
828 web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params);
831 void BrowserPluginGuest::OnImeCancelComposition() {
832 static_cast<RenderWidgetHostViewBase*>(
833 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
836 #if defined(OS_MACOSX) || defined(USE_AURA)
837 void BrowserPluginGuest::OnImeCompositionRangeChanged(
838 const gfx::Range& range,
839 const std::vector<gfx::Rect>& character_bounds) {
840 static_cast<RenderWidgetHostViewBase*>(
841 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
842 range, character_bounds);
846 } // namespace content