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/pickle.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/frame_host/render_widget_host_view_guest.h"
17 #include "content/browser/loader/resource_dispatcher_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_base.h"
21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/browser/web_contents/web_contents_view_guest.h"
23 #include "content/common/browser_plugin/browser_plugin_constants.h"
24 #include "content/common/browser_plugin/browser_plugin_messages.h"
25 #include "content/common/content_constants_internal.h"
26 #include "content/common/drag_messages.h"
27 #include "content/common/frame_messages.h"
28 #include "content/common/input_messages.h"
29 #include "content/common/view_messages.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/browser_plugin_guest_manager.h"
32 #include "content/public/browser/content_browser_client.h"
33 #include "content/public/browser/render_widget_host_view.h"
34 #include "content/public/browser/user_metrics.h"
35 #include "content/public/browser/web_contents_observer.h"
36 #include "content/public/common/drop_data.h"
37 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
39 #if defined(OS_MACOSX)
40 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
45 class BrowserPluginGuest::EmbedderWebContentsObserver
46 : public WebContentsObserver
{
48 explicit EmbedderWebContentsObserver(BrowserPluginGuest
* guest
)
49 : WebContentsObserver(guest
->embedder_web_contents()),
50 browser_plugin_guest_(guest
) {
53 virtual ~EmbedderWebContentsObserver() {
56 // WebContentsObserver implementation.
57 virtual void WasShown() OVERRIDE
{
58 browser_plugin_guest_
->EmbedderVisibilityChanged(true);
61 virtual void WasHidden() OVERRIDE
{
62 browser_plugin_guest_
->EmbedderVisibilityChanged(false);
66 BrowserPluginGuest
* browser_plugin_guest_
;
68 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver
);
71 BrowserPluginGuest::BrowserPluginGuest(bool has_render_view
,
72 WebContentsImpl
* web_contents
,
73 BrowserPluginGuestDelegate
* delegate
)
74 : WebContentsObserver(web_contents
),
75 embedder_web_contents_(NULL
),
76 browser_plugin_instance_id_(browser_plugin::kInstanceIDNone
),
77 guest_device_scale_factor_(1.0f
),
80 pending_lock_request_(false),
81 guest_visible_(false),
83 embedder_visible_(true),
85 has_render_view_(has_render_view
),
86 is_in_destruction_(false),
87 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE
),
88 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT
),
89 last_can_compose_inline_(true),
91 weak_ptr_factory_(this) {
94 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
95 web_contents
->SetBrowserPluginGuest(this);
96 delegate
->RegisterDestructionCallback(
97 base::Bind(&BrowserPluginGuest::WillDestroy
, AsWeakPtr()));
100 void BrowserPluginGuest::WillDestroy() {
101 is_in_destruction_
= true;
102 embedder_web_contents_
= NULL
;
105 base::WeakPtr
<BrowserPluginGuest
> BrowserPluginGuest::AsWeakPtr() {
106 return weak_ptr_factory_
.GetWeakPtr();
109 bool BrowserPluginGuest::LockMouse(bool allowed
) {
110 if (!attached() || (mouse_locked_
== allowed
))
113 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed
);
116 void BrowserPluginGuest::Destroy() {
117 delegate_
->Destroy();
120 WebContentsImpl
* BrowserPluginGuest::CreateNewGuestWindow(
121 const WebContents::CreateParams
& params
) {
122 WebContentsImpl
* new_contents
=
123 static_cast<WebContentsImpl
*>(delegate_
->CreateNewGuestWindow(params
));
124 DCHECK(new_contents
);
128 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
129 const IPC::Message
& message
) {
131 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
132 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK
,
133 OnCompositorFrameSwappedACK
)
134 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck
,
135 OnCopyFromCompositingSurfaceAck
)
136 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate
,
138 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand
,
139 OnExecuteEditCommand
)
140 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete
,
141 OnExtendSelectionAndDelete
)
142 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent
,
144 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition
,
145 OnImeConfirmComposition
)
146 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition
,
148 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK
, OnLockMouseAck
)
149 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed
, OnPluginDestroyed
)
150 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources
,
151 OnReclaimCompositorResources
)
152 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest
, OnResizeGuest
)
153 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent
,
154 OnSetEditCommandsForNextKeyEvent
)
155 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus
, OnSetFocus
)
156 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque
,
158 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility
, OnSetVisibility
)
159 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK
, OnUnlockMouseAck
)
160 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry
, OnUpdateGeometry
)
161 IPC_MESSAGE_UNHANDLED(handled
= false)
162 IPC_END_MESSAGE_MAP()
166 void BrowserPluginGuest::Initialize(
167 int browser_plugin_instance_id
,
168 const BrowserPluginHostMsg_Attach_Params
& params
,
169 WebContentsImpl
* embedder_web_contents
) {
170 browser_plugin_instance_id_
= browser_plugin_instance_id
;
171 focused_
= params
.focused
;
172 guest_visible_
= params
.visible
;
173 guest_opaque_
= params
.opaque
;
174 guest_window_rect_
= gfx::Rect(params
.origin
,
175 params
.resize_guest_params
.view_size
);
177 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
179 embedder_web_contents_
= embedder_web_contents
;
181 WebContentsViewGuest
* new_view
=
182 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
183 new_view
->OnGuestInitialized(embedder_web_contents
->GetView());
185 RendererPreferences
* renderer_prefs
=
186 GetWebContents()->GetMutableRendererPrefs();
187 std::string guest_user_agent_override
= renderer_prefs
->user_agent_override
;
188 // Copy renderer preferences (and nothing else) from the embedder's
189 // WebContents to the guest.
191 // For GTK and Aura this is necessary to get proper renderer configuration
192 // values for caret blinking interval, colors related to selection and
194 *renderer_prefs
= *embedder_web_contents_
->GetMutableRendererPrefs();
195 renderer_prefs
->user_agent_override
= guest_user_agent_override
;
197 // We would like the guest to report changes to frame names so that we can
198 // update the BrowserPlugin's corresponding 'name' attribute.
199 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
200 renderer_prefs
->report_frame_name_changes
= true;
201 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
202 // navigations still continue to function inside the app.
203 renderer_prefs
->browser_handles_all_top_level_requests
= false;
204 // Disable "client blocked" error page for browser plugin.
205 renderer_prefs
->disable_client_blocked_error_page
= true;
207 embedder_web_contents_observer_
.reset(new EmbedderWebContentsObserver(this));
209 OnResizeGuest(browser_plugin_instance_id_
, params
.resize_guest_params
);
211 // Create a swapped out RenderView for the guest in the embedder render
212 // process, so that the embedder can access the guest's window object.
213 int guest_routing_id
=
214 GetWebContents()->CreateSwappedOutRenderView(
215 embedder_web_contents_
->GetSiteInstance());
217 // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
218 // be reset again the next time preferences are updated.
219 WebPreferences prefs
=
220 GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
221 prefs
.navigate_on_drag_drop
= false;
222 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs
);
224 // Enable input method for guest if it's enabled for the embedder.
225 if (static_cast<RenderViewHostImpl
*>(
226 embedder_web_contents_
->GetRenderViewHost())->input_method_active()) {
227 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
228 GetWebContents()->GetRenderViewHost());
229 guest_rvh
->SetInputMethodActive(true);
232 // Inform the embedder of the guest's attachment.
233 SendMessageToEmbedder(
234 new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_
));
236 SendMessageToEmbedder(new BrowserPluginMsg_GuestContentWindowReady(
237 browser_plugin_instance_id_
, guest_routing_id
));
240 BrowserPluginGuest::~BrowserPluginGuest() {
244 BrowserPluginGuest
* BrowserPluginGuest::Create(
245 WebContentsImpl
* web_contents
,
246 BrowserPluginGuestDelegate
* delegate
) {
247 return new BrowserPluginGuest(
248 web_contents
->opener() != NULL
, web_contents
, delegate
);
252 bool BrowserPluginGuest::IsGuest(WebContentsImpl
* web_contents
) {
253 return web_contents
&& web_contents
->GetBrowserPluginGuest();
257 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl
* render_view_host
) {
258 return render_view_host
&& IsGuest(
259 static_cast<WebContentsImpl
*>(WebContents::FromRenderViewHost(
263 RenderWidgetHostView
* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
266 return embedder_web_contents_
->GetRenderWidgetHostView();
269 void BrowserPluginGuest::UpdateVisibility() {
270 OnSetVisibility(browser_plugin_instance_id(), visible());
273 void BrowserPluginGuest::CopyFromCompositingSurface(
274 gfx::Rect src_subrect
,
276 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
277 copy_request_callbacks_
.insert(std::make_pair(++copy_request_id_
, callback
));
278 SendMessageToEmbedder(
279 new BrowserPluginMsg_CopyFromCompositingSurface(
280 browser_plugin_instance_id(),
286 BrowserPluginGuestManager
*
287 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
288 return GetWebContents()->GetBrowserContext()->GetGuestManager();
292 gfx::Rect
BrowserPluginGuest::ToGuestRect(const gfx::Rect
& bounds
) {
293 gfx::Rect
guest_rect(bounds
);
294 guest_rect
.Offset(guest_window_rect_
.OffsetFromOrigin());
295 if (embedder_web_contents()->GetBrowserPluginGuest()) {
296 BrowserPluginGuest
* embedder_guest
=
297 embedder_web_contents()->GetBrowserPluginGuest();
298 guest_rect
.Offset(embedder_guest
->guest_window_rect_
.OffsetFromOrigin());
303 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible
) {
304 embedder_visible_
= visible
;
308 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow
) {
309 SendMessageToEmbedder(
310 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow
));
313 WebContentsImpl
* BrowserPluginGuest::GetWebContents() const {
314 return static_cast<WebContentsImpl
*>(web_contents());
317 gfx::Point
BrowserPluginGuest::GetScreenCoordinates(
318 const gfx::Point
& relative_position
) const {
320 return relative_position
;
322 gfx::Point
screen_pos(relative_position
);
323 screen_pos
+= guest_window_rect_
.OffsetFromOrigin();
324 if (embedder_web_contents()->GetBrowserPluginGuest()) {
325 BrowserPluginGuest
* embedder_guest
=
326 embedder_web_contents()->GetBrowserPluginGuest();
327 screen_pos
+= embedder_guest
->guest_window_rect_
.OffsetFromOrigin();
332 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message
* msg
) {
334 // Some pages such as data URLs, javascript URLs, and about:blank
335 // do not load external resources and so they load prior to attachment.
336 // As a result, we must save all these IPCs until attachment and then
337 // forward them so that the embedder gets a chance to see and process
339 pending_messages_
.push_back(linked_ptr
<IPC::Message
>(msg
));
342 msg
->set_routing_id(embedder_web_contents_
->GetRoutingID());
343 embedder_web_contents_
->Send(msg
);
346 void BrowserPluginGuest::DragSourceEndedAt(int client_x
, int client_y
,
347 int screen_x
, int screen_y
, blink::WebDragOperation operation
) {
348 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x
, client_y
,
349 screen_x
, screen_y
, operation
);
352 void BrowserPluginGuest::EndSystemDrag() {
353 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
354 GetWebContents()->GetRenderViewHost());
355 guest_rvh
->DragSourceSystemDragEnded();
358 void BrowserPluginGuest::SendQueuedMessages() {
362 while (!pending_messages_
.empty()) {
363 linked_ptr
<IPC::Message
> message_ptr
= pending_messages_
.front();
364 pending_messages_
.pop_front();
365 SendMessageToEmbedder(message_ptr
.release());
369 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
370 RenderFrameHost
* render_frame_host
,
372 PageTransition transition_type
) {
373 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
376 void BrowserPluginGuest::RenderViewReady() {
377 RenderViewHost
* rvh
= GetWebContents()->GetRenderViewHost();
378 // TODO(fsamuel): Investigate whether it's possible to update state earlier
379 // here (see http://crbug.com/158151).
380 Send(new InputMsg_SetFocus(routing_id(), focused_
));
383 OnSetContentsOpaque(browser_plugin_instance_id(), guest_opaque_
);
385 RenderWidgetHostImpl::From(rvh
)->set_hung_renderer_delay_ms(
386 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs
));
389 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status
) {
390 SendMessageToEmbedder(
391 new BrowserPluginMsg_GuestGone(browser_plugin_instance_id()));
393 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
394 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
396 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
397 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
399 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
401 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
409 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
410 const IPC::Message
& message
) {
411 switch (message
.type()) {
412 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID
:
413 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID
:
414 case BrowserPluginHostMsg_DragStatusUpdate::ID
:
415 case BrowserPluginHostMsg_ExecuteEditCommand::ID
:
416 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID
:
417 case BrowserPluginHostMsg_HandleInputEvent::ID
:
418 case BrowserPluginHostMsg_ImeConfirmComposition::ID
:
419 case BrowserPluginHostMsg_ImeSetComposition::ID
:
420 case BrowserPluginHostMsg_LockMouse_ACK::ID
:
421 case BrowserPluginHostMsg_PluginDestroyed::ID
:
422 case BrowserPluginHostMsg_ReclaimCompositorResources::ID
:
423 case BrowserPluginHostMsg_ResizeGuest::ID
:
424 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID
:
425 case BrowserPluginHostMsg_SetFocus::ID
:
426 case BrowserPluginHostMsg_SetContentsOpaque::ID
:
427 case BrowserPluginHostMsg_SetVisibility::ID
:
428 case BrowserPluginHostMsg_UnlockMouse_ACK::ID
:
429 case BrowserPluginHostMsg_UpdateGeometry::ID
:
436 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message
& message
) {
438 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
439 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition
,
440 OnImeCancelComposition
)
441 #if defined(OS_MACOSX) || defined(USE_AURA)
442 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged
,
443 OnImeCompositionRangeChanged
)
445 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
446 OnHasTouchEventHandlers
)
447 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
448 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
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 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message
& message
,
461 RenderFrameHost
* render_frame_host
) {
462 // This will eventually be the home for more IPC handlers that depend on
463 // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't
464 // compile if there are no handlers for a platform. So we have both #if guards
465 // around the whole thing (unfortunate but temporary), and #if guards where
466 // they belong, only around the one IPC handler. TODO(avi): Move more of the
467 // frame-based handlers to this function and remove the outer #if layer.
468 #if defined(OS_MACOSX)
470 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest
, message
,
472 #if defined(OS_MACOSX)
473 // MacOS X creates and populates platform-specific select drop-down menus
474 // whereas other platforms merely create a popup window that the guest
475 // renderer process paints inside.
476 IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup
, OnShowPopup
)
478 IPC_MESSAGE_UNHANDLED(handled
= false)
479 IPC_END_MESSAGE_MAP()
486 void BrowserPluginGuest::Attach(
487 int browser_plugin_instance_id
,
488 WebContentsImpl
* embedder_web_contents
,
489 const BrowserPluginHostMsg_Attach_Params
& params
) {
493 delegate_
->WillAttach(embedder_web_contents
);
495 // If a RenderView has already been created for this new window, then we need
496 // to initialize the browser-side state now so that the RenderFrameHostManager
497 // does not create a new RenderView on navigation.
498 if (has_render_view_
) {
499 static_cast<RenderViewHostImpl
*>(
500 GetWebContents()->GetRenderViewHost())->Init();
501 WebContentsViewGuest
* new_view
=
502 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
503 new_view
->CreateViewForWidget(web_contents()->GetRenderViewHost());
506 Initialize(browser_plugin_instance_id
, params
, embedder_web_contents
);
508 SendQueuedMessages();
510 delegate_
->DidAttach();
512 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
515 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
516 int browser_plugin_instance_id
,
517 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
) {
518 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params
.producing_route_id
,
519 params
.output_surface_id
,
520 params
.producing_host_id
,
524 void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id
,
525 blink::WebDragStatus drag_status
,
526 const DropData
& drop_data
,
527 blink::WebDragOperationsMask mask
,
528 const gfx::Point
& location
) {
529 RenderViewHost
* host
= GetWebContents()->GetRenderViewHost();
530 switch (drag_status
) {
531 case blink::WebDragStatusEnter
:
532 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragEnteredGuest(
534 host
->DragTargetDragEnter(drop_data
, location
, location
, mask
, 0);
536 case blink::WebDragStatusOver
:
537 host
->DragTargetDragOver(location
, location
, mask
, 0);
539 case blink::WebDragStatusLeave
:
540 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragLeftGuest(this);
541 host
->DragTargetDragLeave();
543 case blink::WebDragStatusDrop
:
544 host
->DragTargetDrop(location
, location
, 0);
547 case blink::WebDragStatusUnknown
:
552 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id
,
553 const std::string
& name
) {
554 Send(new InputMsg_ExecuteEditCommand(routing_id(), name
, std::string()));
557 void BrowserPluginGuest::OnImeSetComposition(
558 int browser_plugin_instance_id
,
559 const std::string
& text
,
560 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
563 Send(new InputMsg_ImeSetComposition(routing_id(),
564 base::UTF8ToUTF16(text
), underlines
,
565 selection_start
, selection_end
));
568 void BrowserPluginGuest::OnImeConfirmComposition(
569 int browser_plugin_instance_id
,
570 const std::string
& text
,
571 bool keep_selection
) {
572 Send(new InputMsg_ImeConfirmComposition(routing_id(),
573 base::UTF8ToUTF16(text
),
574 gfx::Range::InvalidRange(),
578 void BrowserPluginGuest::OnExtendSelectionAndDelete(
579 int browser_plugin_instance_id
,
582 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(
583 web_contents()->GetFocusedFrame());
585 rfh
->ExtendSelectionAndDelete(before
, after
);
588 void BrowserPluginGuest::OnReclaimCompositorResources(
589 int browser_plugin_instance_id
,
590 const FrameHostMsg_ReclaimCompositorResources_Params
& params
) {
591 RenderWidgetHostImpl::SendReclaimCompositorResources(params
.route_id
,
592 params
.output_surface_id
,
593 params
.renderer_host_id
,
597 void BrowserPluginGuest::OnHandleInputEvent(
598 int browser_plugin_instance_id
,
599 const gfx::Rect
& guest_window_rect
,
600 const blink::WebInputEvent
* event
) {
601 guest_window_rect_
= guest_window_rect
;
602 // If the embedder's RWHV is destroyed then that means that the embedder's
603 // window has been closed but the embedder's WebContents has not yet been
604 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
605 // if there is a visible embedder.
606 if (embedder_web_contents_
->GetRenderWidgetHostView()) {
607 guest_screen_rect_
= guest_window_rect
;
608 guest_screen_rect_
.Offset(
609 embedder_web_contents_
->GetRenderWidgetHostView()->
610 GetViewBounds().OffsetFromOrigin());
612 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
613 GetWebContents()->GetRenderViewHost());
615 if (blink::WebInputEvent::isMouseEventType(event
->type
)) {
616 guest_rvh
->ForwardMouseEvent(
617 *static_cast<const blink::WebMouseEvent
*>(event
));
621 if (event
->type
== blink::WebInputEvent::MouseWheel
) {
622 guest_rvh
->ForwardWheelEvent(
623 *static_cast<const blink::WebMouseWheelEvent
*>(event
));
627 if (blink::WebInputEvent::isKeyboardEventType(event
->type
)) {
628 RenderViewHostImpl
* embedder_rvh
= static_cast<RenderViewHostImpl
*>(
629 embedder_web_contents_
->GetRenderViewHost());
630 if (!embedder_rvh
->GetLastKeyboardEvent())
632 NativeWebKeyboardEvent
keyboard_event(
633 *embedder_rvh
->GetLastKeyboardEvent());
634 guest_rvh
->ForwardKeyboardEvent(keyboard_event
);
638 if (blink::WebInputEvent::isTouchEventType(event
->type
)) {
639 guest_rvh
->ForwardTouchEventWithLatencyInfo(
640 *static_cast<const blink::WebTouchEvent
*>(event
),
645 if (blink::WebInputEvent::isGestureEventType(event
->type
)) {
646 guest_rvh
->ForwardGestureEvent(
647 *static_cast<const blink::WebGestureEvent
*>(event
));
652 void BrowserPluginGuest::OnLockMouse(bool user_gesture
,
653 bool last_unlocked_by_target
,
655 if (pending_lock_request_
) {
656 // Immediately reject the lock because only one pointerLock may be active
658 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
662 pending_lock_request_
= true;
664 delegate_
->RequestPointerLockPermission(
666 last_unlocked_by_target
,
667 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse
,
668 weak_ptr_factory_
.GetWeakPtr()));
671 void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id
,
673 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded
));
674 pending_lock_request_
= false;
676 mouse_locked_
= true;
679 void BrowserPluginGuest::OnPluginDestroyed(int browser_plugin_instance_id
) {
683 void BrowserPluginGuest::OnResizeGuest(
684 int browser_plugin_instance_id
,
685 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
686 if (!params
.size_changed
)
688 // BrowserPlugin manages resize flow control itself and does not depend
689 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
690 // here. If we are setting the size for the first time before navigating then
691 // BrowserPluginGuest does not yet have a RenderViewHost.
692 if (GetWebContents()->GetRenderViewHost()) {
693 RenderWidgetHostImpl
* render_widget_host
=
694 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
695 render_widget_host
->ResetSizeAndRepaintPendingFlags();
697 if (guest_device_scale_factor_
!= params
.scale_factor
) {
698 guest_device_scale_factor_
= params
.scale_factor
;
699 render_widget_host
->NotifyScreenInfoChanged();
703 if (last_seen_browser_plugin_size_
!= params
.view_size
) {
704 delegate_
->ElementSizeChanged(last_seen_browser_plugin_size_
,
706 last_seen_browser_plugin_size_
= params
.view_size
;
709 // Just resize the WebContents and repaint if needed.
710 if (!params
.view_size
.IsEmpty())
711 GetWebContents()->GetView()->SizeContents(params
.view_size
);
713 Send(new ViewMsg_Repaint(routing_id(), params
.view_size
));
716 void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id
,
719 Send(new InputMsg_SetFocus(routing_id(), focused
));
720 if (!focused
&& mouse_locked_
)
723 // Restore the last seen state of text input to the view.
724 RenderWidgetHostViewBase
* rwhv
= static_cast<RenderWidgetHostViewBase
*>(
725 web_contents()->GetRenderWidgetHostView());
727 ViewHostMsg_TextInputState_Params params
;
728 params
.type
= last_text_input_type_
;
729 params
.mode
= last_input_mode_
;
730 params
.can_compose_inline
= last_can_compose_inline_
;
731 rwhv
->TextInputStateChanged(params
);
735 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
736 int browser_plugin_instance_id
,
737 const std::vector
<EditCommand
>& edit_commands
) {
738 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
742 void BrowserPluginGuest::OnSetContentsOpaque(int browser_plugin_instance_id
,
744 guest_opaque_
= opaque
;
745 Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_
));
748 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id
,
750 guest_visible_
= visible
;
751 if (embedder_visible_
&& guest_visible_
)
752 GetWebContents()->WasShown();
754 GetWebContents()->WasHidden();
757 void BrowserPluginGuest::OnUnlockMouse() {
758 SendMessageToEmbedder(
759 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false));
762 void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id
) {
763 // mouse_locked_ could be false here if the lock attempt was cancelled due
764 // to window focus, or for various other reasons before the guest was informed
765 // of the lock's success.
767 Send(new ViewMsg_MouseLockLost(routing_id()));
768 mouse_locked_
= false;
771 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
772 int browser_plugin_instance_id
,
774 const SkBitmap
& bitmap
) {
775 CHECK(copy_request_callbacks_
.count(request_id
));
776 if (!copy_request_callbacks_
.count(request_id
))
778 const CopyRequestCallback
& callback
= copy_request_callbacks_
[request_id
];
779 callback
.Run(!bitmap
.empty() && !bitmap
.isNull(), bitmap
);
780 copy_request_callbacks_
.erase(request_id
);
783 void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id
,
784 const gfx::Rect
& view_rect
) {
785 // The plugin has moved within the embedder without resizing or the
786 // embedder/container's view rect changing.
787 guest_window_rect_
= view_rect
;
788 RenderViewHostImpl
* rvh
= static_cast<RenderViewHostImpl
*>(
789 GetWebContents()->GetRenderViewHost());
791 rvh
->SendScreenRects();
794 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept
) {
795 SendMessageToEmbedder(
796 new BrowserPluginMsg_ShouldAcceptTouchEvents(
797 browser_plugin_instance_id(), accept
));
800 void BrowserPluginGuest::OnSetCursor(const WebCursor
& cursor
) {
801 SendMessageToEmbedder(
802 new BrowserPluginMsg_SetCursor(browser_plugin_instance_id(), cursor
));
805 #if defined(OS_MACOSX)
806 void BrowserPluginGuest::OnShowPopup(
807 RenderFrameHost
* render_frame_host
,
808 const FrameHostMsg_ShowPopup_Params
& params
) {
809 gfx::Rect
translated_bounds(params
.bounds
);
810 translated_bounds
.Offset(guest_window_rect_
.OffsetFromOrigin());
811 BrowserPluginPopupMenuHelper
popup_menu_helper(
812 embedder_web_contents_
->GetRenderViewHost(), render_frame_host
);
813 popup_menu_helper
.ShowPopupMenu(translated_bounds
,
815 params
.item_font_size
,
816 params
.selected_item
,
818 params
.right_aligned
,
819 params
.allow_multiple_selection
);
823 void BrowserPluginGuest::OnShowWidget(int route_id
,
824 const gfx::Rect
& initial_pos
) {
825 GetWebContents()->ShowCreatedWidget(route_id
, initial_pos
);
828 void BrowserPluginGuest::OnTakeFocus(bool reverse
) {
829 SendMessageToEmbedder(
830 new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse
));
833 void BrowserPluginGuest::OnUpdateRect(
834 const ViewHostMsg_UpdateRect_Params
& params
) {
835 BrowserPluginMsg_UpdateRect_Params relay_params
;
836 relay_params
.view_size
= params
.view_size
;
837 relay_params
.scale_factor
= params
.scale_factor
;
838 relay_params
.is_resize_ack
= ViewHostMsg_UpdateRect_Flags::is_resize_ack(
841 if (last_seen_view_size_
!= params
.view_size
) {
842 delegate_
->GuestSizeChanged(last_seen_view_size_
, params
.view_size
);
843 last_seen_view_size_
= params
.view_size
;
846 SendMessageToEmbedder(
847 new BrowserPluginMsg_UpdateRect(browser_plugin_instance_id(),
851 void BrowserPluginGuest::OnTextInputStateChanged(
852 const ViewHostMsg_TextInputState_Params
& params
) {
853 // Save the state of text input so we can restore it on focus.
854 last_text_input_type_
= params
.type
;
855 last_input_mode_
= params
.mode
;
856 last_can_compose_inline_
= params
.can_compose_inline
;
858 static_cast<RenderWidgetHostViewBase
*>(
859 web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params
);
862 void BrowserPluginGuest::OnImeCancelComposition() {
863 static_cast<RenderWidgetHostViewBase
*>(
864 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
867 #if defined(OS_MACOSX) || defined(USE_AURA)
868 void BrowserPluginGuest::OnImeCompositionRangeChanged(
869 const gfx::Range
& range
,
870 const std::vector
<gfx::Rect
>& character_bounds
) {
871 static_cast<RenderWidgetHostViewBase
*>(
872 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
873 range
, character_bounds
);
877 } // namespace content