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),
83 auto_size_enabled_(false),
85 has_render_view_(has_render_view
),
86 last_seen_auto_size_enabled_(false),
87 is_in_destruction_(false),
88 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE
),
89 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT
),
90 last_can_compose_inline_(true),
92 weak_ptr_factory_(this) {
95 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
96 web_contents
->SetBrowserPluginGuest(this);
97 delegate
->RegisterDestructionCallback(
98 base::Bind(&BrowserPluginGuest::WillDestroy
, AsWeakPtr()));
101 void BrowserPluginGuest::WillDestroy() {
102 is_in_destruction_
= true;
103 embedder_web_contents_
= NULL
;
106 base::WeakPtr
<BrowserPluginGuest
> BrowserPluginGuest::AsWeakPtr() {
107 return weak_ptr_factory_
.GetWeakPtr();
110 bool BrowserPluginGuest::LockMouse(bool allowed
) {
111 if (!attached() || (mouse_locked_
== allowed
))
114 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed
);
117 void BrowserPluginGuest::Destroy() {
118 delegate_
->Destroy();
121 WebContentsImpl
* BrowserPluginGuest::CreateNewGuestWindow(
122 const WebContents::CreateParams
& params
) {
123 WebContentsImpl
* new_contents
=
124 static_cast<WebContentsImpl
*>(delegate_
->CreateNewGuestWindow(params
));
125 DCHECK(new_contents
);
129 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
130 const IPC::Message
& message
) {
132 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
133 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK
,
134 OnCompositorFrameSwappedACK
)
135 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck
,
136 OnCopyFromCompositingSurfaceAck
)
137 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate
,
139 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand
,
140 OnExecuteEditCommand
)
141 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete
,
142 OnExtendSelectionAndDelete
)
143 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent
,
145 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition
,
146 OnImeConfirmComposition
)
147 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition
,
149 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK
, OnLockMouseAck
)
150 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed
, OnPluginDestroyed
)
151 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources
,
152 OnReclaimCompositorResources
)
153 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest
, OnResizeGuest
)
154 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize
, OnSetAutoSize
)
155 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent
,
156 OnSetEditCommandsForNextKeyEvent
)
157 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus
, OnSetFocus
)
158 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque
,
160 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility
, OnSetVisibility
)
161 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK
, OnUnlockMouseAck
)
162 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry
, OnUpdateGeometry
)
163 IPC_MESSAGE_UNHANDLED(handled
= false)
164 IPC_END_MESSAGE_MAP()
168 void BrowserPluginGuest::Initialize(
169 const BrowserPluginHostMsg_Attach_Params
& params
,
170 WebContentsImpl
* embedder_web_contents
,
171 const base::DictionaryValue
& extra_params
) {
172 focused_
= params
.focused
;
173 guest_visible_
= params
.visible
;
174 guest_opaque_
= params
.opaque
;
175 guest_window_rect_
= gfx::Rect(params
.origin
,
176 params
.resize_guest_params
.view_size
);
178 auto_size_enabled_
= params
.auto_size_params
.enable
;
179 max_auto_size_
= params
.auto_size_params
.max_size
;
180 min_auto_size_
= params
.auto_size_params
.min_size
;
182 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
184 embedder_web_contents_
= embedder_web_contents
;
186 WebContentsViewGuest
* new_view
=
187 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
188 new_view
->OnGuestInitialized(embedder_web_contents
->GetView());
190 RendererPreferences
* renderer_prefs
=
191 GetWebContents()->GetMutableRendererPrefs();
192 std::string guest_user_agent_override
= renderer_prefs
->user_agent_override
;
193 // Copy renderer preferences (and nothing else) from the embedder's
194 // WebContents to the guest.
196 // For GTK and Aura this is necessary to get proper renderer configuration
197 // values for caret blinking interval, colors related to selection and
199 *renderer_prefs
= *embedder_web_contents_
->GetMutableRendererPrefs();
200 renderer_prefs
->user_agent_override
= guest_user_agent_override
;
202 // We would like the guest to report changes to frame names so that we can
203 // update the BrowserPlugin's corresponding 'name' attribute.
204 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
205 renderer_prefs
->report_frame_name_changes
= true;
206 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
207 // navigations still continue to function inside the app.
208 renderer_prefs
->browser_handles_all_top_level_requests
= false;
209 // Disable "client blocked" error page for browser plugin.
210 renderer_prefs
->disable_client_blocked_error_page
= true;
212 embedder_web_contents_observer_
.reset(new EmbedderWebContentsObserver(this));
215 instance_id_
, params
.auto_size_params
, params
.resize_guest_params
);
217 // Create a swapped out RenderView for the guest in the embedder render
218 // process, so that the embedder can access the guest's window object.
219 int guest_routing_id
=
220 GetWebContents()->CreateSwappedOutRenderView(
221 embedder_web_contents_
->GetSiteInstance());
222 SendMessageToEmbedder(
223 new BrowserPluginMsg_GuestContentWindowReady(instance_id_
,
226 // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
227 // be reset again the next time preferences are updated.
228 WebPreferences prefs
=
229 GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
230 prefs
.navigate_on_drag_drop
= false;
231 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs
);
233 // Enable input method for guest if it's enabled for the embedder.
234 if (static_cast<RenderViewHostImpl
*>(
235 embedder_web_contents_
->GetRenderViewHost())->input_method_active()) {
236 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
237 GetWebContents()->GetRenderViewHost());
238 guest_rvh
->SetInputMethodActive(true);
241 // Inform the embedder of the guest's attachment.
242 SendMessageToEmbedder(new BrowserPluginMsg_Attach_ACK(instance_id_
));
245 BrowserPluginGuest::~BrowserPluginGuest() {
249 BrowserPluginGuest
* BrowserPluginGuest::Create(
251 WebContentsImpl
* web_contents
,
252 BrowserPluginGuestDelegate
* delegate
) {
253 return new BrowserPluginGuest(
254 instance_id
, web_contents
->opener() != NULL
, web_contents
, delegate
);
258 bool BrowserPluginGuest::IsGuest(WebContentsImpl
* web_contents
) {
259 return web_contents
&& web_contents
->GetBrowserPluginGuest();
263 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl
* render_view_host
) {
264 return render_view_host
&& IsGuest(
265 static_cast<WebContentsImpl
*>(WebContents::FromRenderViewHost(
269 RenderWidgetHostView
* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
272 return embedder_web_contents_
->GetRenderWidgetHostView();
275 void BrowserPluginGuest::UpdateVisibility() {
276 OnSetVisibility(instance_id_
, visible());
279 void BrowserPluginGuest::CopyFromCompositingSurface(
280 gfx::Rect src_subrect
,
282 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
283 copy_request_callbacks_
.insert(std::make_pair(++copy_request_id_
, callback
));
284 SendMessageToEmbedder(
285 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
286 copy_request_id_
, src_subrect
, dst_size
));
289 BrowserPluginGuestManager
*
290 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
291 return GetWebContents()->GetBrowserContext()->GetGuestManager();
295 gfx::Rect
BrowserPluginGuest::ToGuestRect(const gfx::Rect
& bounds
) {
296 gfx::Rect
guest_rect(bounds
);
297 guest_rect
.Offset(guest_window_rect_
.OffsetFromOrigin());
298 if (embedder_web_contents()->GetBrowserPluginGuest()) {
299 BrowserPluginGuest
* embedder_guest
=
300 embedder_web_contents()->GetBrowserPluginGuest();
301 guest_rect
.Offset(embedder_guest
->guest_window_rect_
.OffsetFromOrigin());
306 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible
) {
307 embedder_visible_
= visible
;
311 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow
) {
312 SendMessageToEmbedder(
313 new BrowserPluginMsg_SetMouseLock(instance_id(), allow
));
316 WebContentsImpl
* BrowserPluginGuest::GetWebContents() const {
317 return static_cast<WebContentsImpl
*>(web_contents());
320 gfx::Point
BrowserPluginGuest::GetScreenCoordinates(
321 const gfx::Point
& relative_position
) const {
323 return relative_position
;
325 gfx::Point
screen_pos(relative_position
);
326 screen_pos
+= guest_window_rect_
.OffsetFromOrigin();
327 if (embedder_web_contents()->GetBrowserPluginGuest()) {
328 BrowserPluginGuest
* embedder_guest
=
329 embedder_web_contents()->GetBrowserPluginGuest();
330 screen_pos
+= embedder_guest
->guest_window_rect_
.OffsetFromOrigin();
335 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size
& size
) const {
336 return size
.width() <= max_auto_size_
.width() &&
337 size
.height() <= max_auto_size_
.height();
340 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message
* msg
) {
342 // Some pages such as data URLs, javascript URLs, and about:blank
343 // do not load external resources and so they load prior to attachment.
344 // As a result, we must save all these IPCs until attachment and then
345 // forward them so that the embedder gets a chance to see and process
347 pending_messages_
.push_back(linked_ptr
<IPC::Message
>(msg
));
350 msg
->set_routing_id(embedder_web_contents_
->GetRoutingID());
351 embedder_web_contents_
->Send(msg
);
354 void BrowserPluginGuest::DragSourceEndedAt(int client_x
, int client_y
,
355 int screen_x
, int screen_y
, blink::WebDragOperation operation
) {
356 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x
, client_y
,
357 screen_x
, screen_y
, operation
);
360 void BrowserPluginGuest::EndSystemDrag() {
361 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
362 GetWebContents()->GetRenderViewHost());
363 guest_rvh
->DragSourceSystemDragEnded();
366 void BrowserPluginGuest::SendQueuedMessages() {
370 while (!pending_messages_
.empty()) {
371 linked_ptr
<IPC::Message
> message_ptr
= pending_messages_
.front();
372 pending_messages_
.pop_front();
373 SendMessageToEmbedder(message_ptr
.release());
377 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
378 RenderFrameHost
* render_frame_host
,
380 PageTransition transition_type
) {
381 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
384 void BrowserPluginGuest::RenderViewReady() {
385 RenderViewHost
* rvh
= GetWebContents()->GetRenderViewHost();
386 // TODO(fsamuel): Investigate whether it's possible to update state earlier
387 // here (see http://crbug.com/158151).
388 Send(new InputMsg_SetFocus(routing_id(), focused_
));
390 if (auto_size_enabled_
)
391 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
393 rvh
->DisableAutoResize(full_size_
);
395 OnSetContentsOpaque(instance_id_
, guest_opaque_
);
397 RenderWidgetHostImpl::From(rvh
)->set_hung_renderer_delay_ms(
398 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs
));
401 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status
) {
402 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
404 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
405 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
407 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
408 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
410 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
412 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
420 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
421 const IPC::Message
& message
) {
422 switch (message
.type()) {
423 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID
:
424 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID
:
425 case BrowserPluginHostMsg_DragStatusUpdate::ID
:
426 case BrowserPluginHostMsg_ExecuteEditCommand::ID
:
427 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID
:
428 case BrowserPluginHostMsg_HandleInputEvent::ID
:
429 case BrowserPluginHostMsg_ImeConfirmComposition::ID
:
430 case BrowserPluginHostMsg_ImeSetComposition::ID
:
431 case BrowserPluginHostMsg_LockMouse_ACK::ID
:
432 case BrowserPluginHostMsg_PluginDestroyed::ID
:
433 case BrowserPluginHostMsg_ReclaimCompositorResources::ID
:
434 case BrowserPluginHostMsg_ResizeGuest::ID
:
435 case BrowserPluginHostMsg_SetAutoSize::ID
:
436 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID
:
437 case BrowserPluginHostMsg_SetFocus::ID
:
438 case BrowserPluginHostMsg_SetContentsOpaque::ID
:
439 case BrowserPluginHostMsg_SetVisibility::ID
:
440 case BrowserPluginHostMsg_UnlockMouse_ACK::ID
:
441 case BrowserPluginHostMsg_UpdateGeometry::ID
:
448 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message
& message
) {
450 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
451 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition
,
452 OnImeCancelComposition
)
453 #if defined(OS_MACOSX) || defined(USE_AURA)
454 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged
,
455 OnImeCompositionRangeChanged
)
457 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
458 OnHasTouchEventHandlers
)
459 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
460 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
461 #if defined(OS_MACOSX)
462 // MacOSX creates and populates platform-specific select drop-down menus
463 // whereas other platforms merely create a popup window that the guest
464 // renderer process paints inside.
465 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup
, OnShowPopup
)
467 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget
, OnShowWidget
)
468 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus
, OnTakeFocus
)
469 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged
,
470 OnTextInputStateChanged
)
471 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnUnlockMouse
)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnUpdateRect
)
473 IPC_MESSAGE_UNHANDLED(handled
= false)
474 IPC_END_MESSAGE_MAP()
478 void BrowserPluginGuest::Attach(
479 WebContentsImpl
* embedder_web_contents
,
480 const BrowserPluginHostMsg_Attach_Params
& params
,
481 const base::DictionaryValue
& extra_params
) {
486 delegate_
->WillAttach(embedder_web_contents
, extra_params
);
488 // If a RenderView has already been created for this new window, then we need
489 // to initialize the browser-side state now so that the RenderFrameHostManager
490 // does not create a new RenderView on navigation.
491 if (has_render_view_
) {
492 static_cast<RenderViewHostImpl
*>(
493 GetWebContents()->GetRenderViewHost())->Init();
494 WebContentsViewGuest
* new_view
=
495 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
496 new_view
->CreateViewForWidget(web_contents()->GetRenderViewHost());
499 Initialize(params
, embedder_web_contents
, extra_params
);
501 SendQueuedMessages();
504 delegate_
->DidAttach();
506 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
509 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
511 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
) {
512 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params
.producing_route_id
,
513 params
.output_surface_id
,
514 params
.producing_host_id
,
518 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id
,
519 blink::WebDragStatus drag_status
,
520 const DropData
& drop_data
,
521 blink::WebDragOperationsMask mask
,
522 const gfx::Point
& location
) {
523 RenderViewHost
* host
= GetWebContents()->GetRenderViewHost();
524 switch (drag_status
) {
525 case blink::WebDragStatusEnter
:
526 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragEnteredGuest(
528 host
->DragTargetDragEnter(drop_data
, location
, location
, mask
, 0);
530 case blink::WebDragStatusOver
:
531 host
->DragTargetDragOver(location
, location
, mask
, 0);
533 case blink::WebDragStatusLeave
:
534 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragLeftGuest(this);
535 host
->DragTargetDragLeave();
537 case blink::WebDragStatusDrop
:
538 host
->DragTargetDrop(location
, location
, 0);
541 case blink::WebDragStatusUnknown
:
546 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id
,
547 const std::string
& name
) {
548 Send(new InputMsg_ExecuteEditCommand(routing_id(), name
, std::string()));
551 void BrowserPluginGuest::OnImeSetComposition(
553 const std::string
& text
,
554 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
557 Send(new InputMsg_ImeSetComposition(routing_id(),
558 base::UTF8ToUTF16(text
), underlines
,
559 selection_start
, selection_end
));
562 void BrowserPluginGuest::OnImeConfirmComposition(
564 const std::string
& text
,
565 bool keep_selection
) {
566 Send(new InputMsg_ImeConfirmComposition(routing_id(),
567 base::UTF8ToUTF16(text
),
568 gfx::Range::InvalidRange(),
572 void BrowserPluginGuest::OnExtendSelectionAndDelete(
576 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(
577 web_contents()->GetFocusedFrame());
579 rfh
->ExtendSelectionAndDelete(before
, after
);
582 void BrowserPluginGuest::OnReclaimCompositorResources(
584 const FrameHostMsg_ReclaimCompositorResources_Params
& params
) {
585 RenderWidgetHostImpl::SendReclaimCompositorResources(params
.route_id
,
586 params
.output_surface_id
,
587 params
.renderer_host_id
,
591 void BrowserPluginGuest::OnHandleInputEvent(
593 const gfx::Rect
& guest_window_rect
,
594 const blink::WebInputEvent
* event
) {
595 guest_window_rect_
= guest_window_rect
;
596 // If the embedder's RWHV is destroyed then that means that the embedder's
597 // window has been closed but the embedder's WebContents has not yet been
598 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
599 // if there is a visible embedder.
600 if (embedder_web_contents_
->GetRenderWidgetHostView()) {
601 guest_screen_rect_
= guest_window_rect
;
602 guest_screen_rect_
.Offset(
603 embedder_web_contents_
->GetRenderWidgetHostView()->
604 GetViewBounds().OffsetFromOrigin());
606 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
607 GetWebContents()->GetRenderViewHost());
609 if (blink::WebInputEvent::isMouseEventType(event
->type
)) {
610 guest_rvh
->ForwardMouseEvent(
611 *static_cast<const blink::WebMouseEvent
*>(event
));
615 if (event
->type
== blink::WebInputEvent::MouseWheel
) {
616 guest_rvh
->ForwardWheelEvent(
617 *static_cast<const blink::WebMouseWheelEvent
*>(event
));
621 if (blink::WebInputEvent::isKeyboardEventType(event
->type
)) {
622 RenderViewHostImpl
* embedder_rvh
= static_cast<RenderViewHostImpl
*>(
623 embedder_web_contents_
->GetRenderViewHost());
624 if (!embedder_rvh
->GetLastKeyboardEvent())
626 NativeWebKeyboardEvent
keyboard_event(
627 *embedder_rvh
->GetLastKeyboardEvent());
628 guest_rvh
->ForwardKeyboardEvent(keyboard_event
);
632 if (blink::WebInputEvent::isTouchEventType(event
->type
)) {
633 guest_rvh
->ForwardTouchEventWithLatencyInfo(
634 *static_cast<const blink::WebTouchEvent
*>(event
),
639 if (blink::WebInputEvent::isGestureEventType(event
->type
)) {
640 guest_rvh
->ForwardGestureEvent(
641 *static_cast<const blink::WebGestureEvent
*>(event
));
646 void BrowserPluginGuest::OnLockMouse(bool user_gesture
,
647 bool last_unlocked_by_target
,
649 if (pending_lock_request_
) {
650 // Immediately reject the lock because only one pointerLock may be active
652 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
656 pending_lock_request_
= true;
658 delegate_
->RequestPointerLockPermission(
660 last_unlocked_by_target
,
661 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse
,
662 weak_ptr_factory_
.GetWeakPtr()));
665 void BrowserPluginGuest::OnLockMouseAck(int instance_id
, bool succeeded
) {
666 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded
));
667 pending_lock_request_
= false;
669 mouse_locked_
= true;
672 void BrowserPluginGuest::OnPluginDestroyed(int instance_id
) {
676 void BrowserPluginGuest::OnResizeGuest(
678 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
679 if (!params
.size_changed
)
681 // BrowserPlugin manages resize flow control itself and does not depend
682 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
683 // here. If we are setting the size for the first time before navigating then
684 // BrowserPluginGuest does not yet have a RenderViewHost.
685 if (GetWebContents()->GetRenderViewHost()) {
686 RenderWidgetHostImpl
* render_widget_host
=
687 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
688 render_widget_host
->ResetSizeAndRepaintPendingFlags();
690 if (guest_device_scale_factor_
!= params
.scale_factor
) {
691 guest_device_scale_factor_
= params
.scale_factor
;
692 render_widget_host
->NotifyScreenInfoChanged();
695 // When autosize is turned off and as a result there is a layout change, we
696 // send a sizechanged event.
697 if (!auto_size_enabled_
&& last_seen_auto_size_enabled_
&&
698 !params
.view_size
.IsEmpty()) {
699 delegate_
->SizeChanged(last_seen_view_size_
, params
.view_size
);
700 last_seen_auto_size_enabled_
= false;
702 // Just resize the WebContents and repaint if needed.
703 full_size_
= params
.view_size
;
704 if (!params
.view_size
.IsEmpty())
705 GetWebContents()->GetView()->SizeContents(params
.view_size
);
707 Send(new ViewMsg_Repaint(routing_id(), params
.view_size
));
710 void BrowserPluginGuest::OnSetFocus(int instance_id
, bool focused
) {
712 Send(new InputMsg_SetFocus(routing_id(), focused
));
713 if (!focused
&& mouse_locked_
)
716 // Restore the last seen state of text input to the view.
717 RenderWidgetHostViewBase
* rwhv
= static_cast<RenderWidgetHostViewBase
*>(
718 web_contents()->GetRenderWidgetHostView());
720 ViewHostMsg_TextInputState_Params params
;
721 params
.type
= last_text_input_type_
;
722 params
.mode
= last_input_mode_
;
723 params
.can_compose_inline
= last_can_compose_inline_
;
724 rwhv
->TextInputStateChanged(params
);
728 void BrowserPluginGuest::OnSetAutoSize(
730 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
731 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
732 bool old_auto_size_enabled
= auto_size_enabled_
;
733 gfx::Size old_max_size
= max_auto_size_
;
734 gfx::Size old_min_size
= min_auto_size_
;
735 auto_size_enabled_
= auto_size_params
.enable
;
736 max_auto_size_
= auto_size_params
.max_size
;
737 min_auto_size_
= auto_size_params
.min_size
;
738 if (auto_size_enabled_
&& (!old_auto_size_enabled
||
739 (old_max_size
!= max_auto_size_
) ||
740 (old_min_size
!= min_auto_size_
))) {
742 base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
743 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
744 min_auto_size_
, max_auto_size_
);
745 // TODO(fsamuel): If we're changing autosize parameters, then we force
746 // the guest to completely repaint itself.
747 // Ideally, we shouldn't need to do this unless |max_auto_size_| has
749 // However, even in that case, layout may not change and so we may
750 // not get a full frame worth of pixels.
751 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_
));
752 } else if (!auto_size_enabled_
&& old_auto_size_enabled
) {
753 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
754 resize_guest_params
.view_size
);
756 OnResizeGuest(instance_id_
, resize_guest_params
);
759 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
761 const std::vector
<EditCommand
>& edit_commands
) {
762 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
766 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id
, bool opaque
) {
767 guest_opaque_
= opaque
;
768 Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_
));
771 void BrowserPluginGuest::OnSetVisibility(int instance_id
, bool visible
) {
772 guest_visible_
= visible
;
773 if (embedder_visible_
&& guest_visible_
)
774 GetWebContents()->WasShown();
776 GetWebContents()->WasHidden();
779 void BrowserPluginGuest::OnUnlockMouse() {
780 SendMessageToEmbedder(
781 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
784 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id
) {
785 // mouse_locked_ could be false here if the lock attempt was cancelled due
786 // to window focus, or for various other reasons before the guest was informed
787 // of the lock's success.
789 Send(new ViewMsg_MouseLockLost(routing_id()));
790 mouse_locked_
= false;
793 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
796 const SkBitmap
& bitmap
) {
797 CHECK(copy_request_callbacks_
.count(request_id
));
798 if (!copy_request_callbacks_
.count(request_id
))
800 const CopyRequestCallback
& callback
= copy_request_callbacks_
[request_id
];
801 callback
.Run(!bitmap
.empty() && !bitmap
.isNull(), bitmap
);
802 copy_request_callbacks_
.erase(request_id
);
805 void BrowserPluginGuest::OnUpdateGeometry(int instance_id
,
806 const gfx::Rect
& view_rect
) {
807 // The plugin has moved within the embedder without resizing or the
808 // embedder/container's view rect changing.
809 guest_window_rect_
= view_rect
;
810 RenderViewHostImpl
* rvh
= static_cast<RenderViewHostImpl
*>(
811 GetWebContents()->GetRenderViewHost());
813 rvh
->SendScreenRects();
816 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept
) {
817 SendMessageToEmbedder(
818 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept
));
821 void BrowserPluginGuest::OnSetCursor(const WebCursor
& cursor
) {
822 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor
));
825 #if defined(OS_MACOSX)
826 void BrowserPluginGuest::OnShowPopup(
827 const ViewHostMsg_ShowPopup_Params
& params
) {
828 gfx::Rect
translated_bounds(params
.bounds
);
829 translated_bounds
.Offset(guest_window_rect_
.OffsetFromOrigin());
830 BrowserPluginPopupMenuHelper
popup_menu_helper(
831 embedder_web_contents_
->GetRenderViewHost(),
832 GetWebContents()->GetRenderViewHost());
833 popup_menu_helper
.ShowPopupMenu(translated_bounds
,
835 params
.item_font_size
,
836 params
.selected_item
,
838 params
.right_aligned
,
839 params
.allow_multiple_selection
);
843 void BrowserPluginGuest::OnShowWidget(int route_id
,
844 const gfx::Rect
& initial_pos
) {
845 GetWebContents()->ShowCreatedWidget(route_id
, initial_pos
);
848 void BrowserPluginGuest::OnTakeFocus(bool reverse
) {
849 SendMessageToEmbedder(
850 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse
));
853 void BrowserPluginGuest::OnUpdateRect(
854 const ViewHostMsg_UpdateRect_Params
& params
) {
855 BrowserPluginMsg_UpdateRect_Params relay_params
;
856 relay_params
.view_size
= params
.view_size
;
857 relay_params
.scale_factor
= params
.scale_factor
;
858 relay_params
.is_resize_ack
= ViewHostMsg_UpdateRect_Flags::is_resize_ack(
861 bool size_changed
= last_seen_view_size_
!= params
.view_size
;
862 gfx::Size old_size
= last_seen_view_size_
;
863 last_seen_view_size_
= params
.view_size
;
865 if ((auto_size_enabled_
|| last_seen_auto_size_enabled_
) &&
867 delegate_
->SizeChanged(old_size
, last_seen_view_size_
);
869 last_seen_auto_size_enabled_
= auto_size_enabled_
;
871 SendMessageToEmbedder(
872 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params
));
875 void BrowserPluginGuest::OnTextInputStateChanged(
876 const ViewHostMsg_TextInputState_Params
& params
) {
877 // Save the state of text input so we can restore it on focus.
878 last_text_input_type_
= params
.type
;
879 last_input_mode_
= params
.mode
;
880 last_can_compose_inline_
= params
.can_compose_inline
;
882 static_cast<RenderWidgetHostViewBase
*>(
883 web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params
);
886 void BrowserPluginGuest::OnImeCancelComposition() {
887 static_cast<RenderWidgetHostViewBase
*>(
888 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
891 #if defined(OS_MACOSX) || defined(USE_AURA)
892 void BrowserPluginGuest::OnImeCompositionRangeChanged(
893 const gfx::Range
& range
,
894 const std::vector
<gfx::Rect
>& character_bounds
) {
895 static_cast<RenderWidgetHostViewBase
*>(
896 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
897 range
, character_bounds
);
901 } // namespace content