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.h"
10 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
13 #include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
14 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
15 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/browser/renderer_host/render_widget_host_impl.h"
18 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/common/browser_plugin/browser_plugin_constants.h"
20 #include "content/common/browser_plugin/browser_plugin_messages.h"
21 #include "content/common/content_constants_internal.h"
22 #include "content/common/drag_messages.h"
23 #include "content/common/gpu/gpu_messages.h"
24 #include "content/common/view_messages.h"
25 #include "content/port/browser/render_view_host_delegate_view.h"
26 #include "content/public/browser/browser_context.h"
27 #include "content/public/browser/content_browser_client.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/notification_types.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_widget_host_view.h"
32 #include "content/public/browser/resource_request_details.h"
33 #include "content/public/browser/user_metrics.h"
34 #include "content/public/browser/web_contents_view.h"
35 #include "content/public/common/media_stream_request.h"
36 #include "content/public/common/result_codes.h"
37 #include "net/base/net_errors.h"
38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
39 #include "ui/surface/transport_dib.h"
40 #include "webkit/glue/resource_type.h"
41 #include "webkit/glue/webdropdata.h"
43 #if defined(OS_MACOSX)
44 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
50 BrowserPluginHostFactory
* BrowserPluginGuest::factory_
= NULL
;
53 const size_t kNumMaxOutstandingMediaRequests
= 1024;
56 BrowserPluginGuest::BrowserPluginGuest(
58 WebContentsImpl
* web_contents
,
59 const BrowserPluginHostMsg_CreateGuest_Params
& params
)
60 : WebContentsObserver(web_contents
),
61 embedder_web_contents_(NULL
),
62 instance_id_(instance_id
),
63 damage_buffer_sequence_id_(0),
64 damage_buffer_size_(0),
65 damage_buffer_scale_factor_(1.0f
),
67 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs
)),
68 focused_(params
.focused
),
70 guest_visible_(params
.visible
),
71 embedder_visible_(true),
73 auto_size_enabled_(params
.auto_size_params
.enable
),
74 max_auto_size_(params
.auto_size_params
.max_size
),
75 min_auto_size_(params
.auto_size_params
.min_size
),
76 current_media_access_request_id_(0) {
78 web_contents
->SetDelegate(this);
79 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_
,
83 void BrowserPluginGuest::Destroy() {
84 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_
);
85 delete GetWebContents();
88 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
89 const IPC::Message
& message
) {
91 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
92 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK
,
94 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate
,
96 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go
, OnGo
)
97 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent
,
99 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK
, OnLockMouseAck
)
100 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest
, OnNavigateGuest
)
101 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed
, OnPluginDestroyed
)
102 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Reload
, OnReload
)
103 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest
, OnResizeGuest
)
104 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_RespondPermission
,
106 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize
, OnSetSize
)
107 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus
, OnSetFocus
)
108 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName
, OnSetName
)
109 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility
, OnSetVisibility
)
110 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Stop
, OnStop
)
111 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_TerminateGuest
, OnTerminateGuest
)
112 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK
, OnUnlockMouseAck
)
113 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK
, OnUpdateRectACK
)
114 IPC_MESSAGE_UNHANDLED(handled
= false)
115 IPC_END_MESSAGE_MAP()
119 void BrowserPluginGuest::Initialize(
120 WebContentsImpl
* embedder_web_contents
,
121 const BrowserPluginHostMsg_CreateGuest_Params
& params
) {
122 // |render_view_host| manages the ownership of this BrowserPluginGuestHelper.
123 new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost());
125 embedder_web_contents_
= embedder_web_contents
;
127 RendererPreferences
* renderer_prefs
=
128 GetWebContents()->GetMutableRendererPrefs();
129 // Copy renderer preferences (and nothing else) from the embedder's
130 // WebContents to the guest.
132 // For GTK and Aura this is necessary to get proper renderer configuration
133 // values for caret blinking interval, colors related to selection and
135 *renderer_prefs
= *embedder_web_contents_
->GetMutableRendererPrefs();
137 renderer_prefs
->throttle_input_events
= false;
138 // We would like the guest to report changes to frame names so that we can
139 // update the BrowserPlugin's corresponding 'name' attribute.
140 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
141 renderer_prefs
->report_frame_name_changes
= true;
142 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
143 // navigations still continue to function inside the app.
144 renderer_prefs
->browser_handles_all_top_level_requests
= false;
146 notification_registrar_
.Add(
147 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
,
148 Source
<WebContents
>(GetWebContents()));
150 // Listen to embedder visibility changes so that the guest is in a 'shown'
151 // state if both the embedder is visible and the BrowserPlugin is marked as
153 notification_registrar_
.Add(
154 this, content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
,
155 Source
<WebContents
>(embedder_web_contents_
));
157 notification_registrar_
.Add(
158 this, content::NOTIFICATION_RENDER_VIEW_HOST_DELETED
,
159 Source
<RenderViewHost
>(embedder_web_contents_
->GetRenderViewHost()));
161 OnSetSize(instance_id_
, params
.auto_size_params
, params
.resize_guest_params
);
163 // Create a swapped out RenderView for the guest in the embedder render
164 // process, so that the embedder can access the guest's window object.
165 int guest_routing_id
=
166 GetWebContents()->CreateSwappedOutRenderView(
167 embedder_web_contents_
->GetSiteInstance());
168 SendMessageToEmbedder(
169 new BrowserPluginMsg_GuestContentWindowReady(instance_id_
,
172 if (!params
.src
.empty())
173 OnNavigateGuest(instance_id_
, params
.src
);
175 GetContentClient()->browser()->GuestWebContentsCreated(
176 GetWebContents(), embedder_web_contents_
);
179 BrowserPluginGuest::~BrowserPluginGuest() {
183 BrowserPluginGuest
* BrowserPluginGuest::Create(
185 WebContentsImpl
* web_contents
,
186 const BrowserPluginHostMsg_CreateGuest_Params
& params
) {
187 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
189 return factory_
->CreateBrowserPluginGuest(instance_id
,
193 return new BrowserPluginGuest(instance_id
, web_contents
, params
);
196 RenderWidgetHostView
* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
197 return embedder_web_contents_
->GetRenderWidgetHostView();
200 void BrowserPluginGuest::UpdateVisibility() {
201 OnSetVisibility(instance_id_
, visible());
204 void BrowserPluginGuest::Observe(int type
,
205 const NotificationSource
& source
,
206 const NotificationDetails
& details
) {
208 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
: {
209 DCHECK_EQ(Source
<WebContents
>(source
).ptr(), GetWebContents());
210 ResourceRedirectDetails
* resource_redirect_details
=
211 Details
<ResourceRedirectDetails
>(details
).ptr();
213 resource_redirect_details
->resource_type
== ResourceType::MAIN_FRAME
;
214 LoadRedirect(resource_redirect_details
->url
,
215 resource_redirect_details
->new_url
,
219 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED
: {
220 DCHECK_EQ(Source
<WebContents
>(source
).ptr(), embedder_web_contents_
);
221 embedder_visible_
= *Details
<bool>(details
).ptr();
225 case NOTIFICATION_RENDER_VIEW_HOST_DELETED
: {
230 NOTREACHED() << "Unexpected notification sent.";
235 bool BrowserPluginGuest::CanDownload(RenderViewHost
* render_view_host
,
237 const std::string
& request_method
) {
238 // TODO(fsamuel): We disable downloads in guests for now, but we will later
239 // expose API to allow embedders to handle them.
240 // Note: it seems content_shell ignores this. This should be fixed
241 // for debugging and test purposes.
245 bool BrowserPluginGuest::HandleContextMenu(
246 const ContextMenuParams
& params
) {
247 // TODO(fsamuel): We have a do nothing context menu handler for now until
248 // we implement the Apps Context Menu API for Browser Plugin (see
249 // http://crbug.com/140315).
253 void BrowserPluginGuest::RendererUnresponsive(WebContents
* source
) {
255 GetWebContents()->GetRenderProcessHost()->GetID();
256 SendMessageToEmbedder(
257 new BrowserPluginMsg_GuestUnresponsive(instance_id(), process_id
));
258 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
261 void BrowserPluginGuest::RendererResponsive(WebContents
* source
) {
263 GetWebContents()->GetRenderProcessHost()->GetID();
264 SendMessageToEmbedder(
265 new BrowserPluginMsg_GuestResponsive(instance_id(), process_id
));
266 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
269 void BrowserPluginGuest::RunFileChooser(WebContents
* web_contents
,
270 const FileChooserParams
& params
) {
271 embedder_web_contents_
->GetDelegate()->RunFileChooser(web_contents
, params
);
274 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
275 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
276 // manage the focus ourselves.
280 WebContentsImpl
* BrowserPluginGuest::GetWebContents() {
281 return static_cast<WebContentsImpl
*>(web_contents());
284 base::SharedMemory
* BrowserPluginGuest::GetDamageBufferFromEmbedder(
285 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
287 base::ProcessHandle handle
=
288 embedder_web_contents_
->GetRenderProcessHost()->GetHandle();
289 scoped_ptr
<base::SharedMemory
> shared_buf(
290 new base::SharedMemory(params
.damage_buffer_handle
, false, handle
));
291 #elif defined(OS_POSIX)
292 scoped_ptr
<base::SharedMemory
> shared_buf(
293 new base::SharedMemory(params
.damage_buffer_handle
, false));
295 if (!shared_buf
->Map(params
.damage_buffer_size
)) {
299 return shared_buf
.release();
302 void BrowserPluginGuest::SetDamageBuffer(
303 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
304 damage_buffer_
.reset(GetDamageBufferFromEmbedder(params
));
305 // Sanity check: Verify that we've correctly shared the damage buffer memory
306 // between the embedder and browser processes.
307 DCHECK(*static_cast<unsigned int*>(damage_buffer_
->memory()) == 0xdeadbeef);
308 damage_buffer_sequence_id_
= params
.damage_buffer_sequence_id
;
309 damage_buffer_size_
= params
.damage_buffer_size
;
310 damage_view_size_
= params
.view_size
;
311 damage_buffer_scale_factor_
= params
.scale_factor
;
314 gfx::Point
BrowserPluginGuest::GetScreenCoordinates(
315 const gfx::Point
& relative_position
) const {
316 gfx::Point
screen_pos(relative_position
);
317 screen_pos
+= guest_window_rect_
.OffsetFromOrigin();
321 int BrowserPluginGuest::embedder_routing_id() const {
322 return embedder_web_contents_
->GetRoutingID();
325 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size
& size
) const {
326 return size
.width() <= max_auto_size_
.width() &&
327 size
.height() <= max_auto_size_
.height();
330 void BrowserPluginGuest::DidStartProvisionalLoadForFrame(
332 int64 parent_frame_id
,
334 const GURL
& validated_url
,
336 bool is_iframe_srcdoc
,
337 RenderViewHost
* render_view_host
) {
338 // Inform the embedder of the loadStart.
339 SendMessageToEmbedder(
340 new BrowserPluginMsg_LoadStart(instance_id(),
345 void BrowserPluginGuest::DidFailProvisionalLoad(
348 const GURL
& validated_url
,
350 const string16
& error_description
,
351 RenderViewHost
* render_view_host
) {
352 // Translate the |error_code| into an error string.
353 std::string error_type
;
354 RemoveChars(net::ErrorToString(error_code
), "net::", &error_type
);
355 // Inform the embedder of the loadAbort.
356 SendMessageToEmbedder(
357 new BrowserPluginMsg_LoadAbort(instance_id(),
363 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message
* msg
) {
364 msg
->set_routing_id(embedder_routing_id());
365 embedder_web_contents_
->Send(msg
);
368 void BrowserPluginGuest::LoadRedirect(
372 SendMessageToEmbedder(
373 new BrowserPluginMsg_LoadRedirect(instance_id(),
379 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
383 PageTransition transition_type
,
384 RenderViewHost
* render_view_host
) {
385 // Inform its embedder of the updated URL.
386 BrowserPluginMsg_LoadCommit_Params params
;
388 params
.is_top_level
= is_main_frame
;
389 params
.process_id
= render_view_host
->GetProcess()->GetID();
390 params
.route_id
= render_view_host
->GetRoutingID();
391 params
.current_entry_index
=
392 GetWebContents()->GetController().GetCurrentEntryIndex();
394 GetWebContents()->GetController().GetEntryCount();
395 SendMessageToEmbedder(
396 new BrowserPluginMsg_LoadCommit(instance_id(), params
));
397 RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
400 void BrowserPluginGuest::DidStopLoading(RenderViewHost
* render_view_host
) {
401 // Initiating a drag from inside a guest is currently not supported. So inject
402 // some JS to disable it. http://crbug.com/161112
403 const char script
[] = "window.addEventListener('dragstart', function() { "
404 " window.event.preventDefault(); "
406 render_view_host
->ExecuteJavascriptInWebFrame(string16(),
407 ASCIIToUTF16(script
));
408 SendMessageToEmbedder(new BrowserPluginMsg_LoadStop(instance_id()));
411 void BrowserPluginGuest::RenderViewReady() {
412 // TODO(fsamuel): Investigate whether it's possible to update state earlier
413 // here (see http://crbug.com/158151).
414 Send(new ViewMsg_SetFocus(routing_id(), focused_
));
416 RenderViewHost
* rvh
= GetWebContents()->GetRenderViewHost();
417 if (auto_size_enabled_
)
418 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
420 rvh
->DisableAutoResize(damage_view_size_
);
422 Send(new ViewMsg_SetName(routing_id(), name_
));
425 void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status
) {
426 int process_id
= GetWebContents()->GetRenderProcessHost()->GetID();
427 SendMessageToEmbedder(
428 new BrowserPluginMsg_GuestGone(instance_id(), process_id
, status
));
430 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
431 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
433 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
434 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
436 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
437 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
445 void BrowserPluginGuest::AcknowledgeBufferPresent(
448 const gpu::Mailbox
& mailbox_name
,
450 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
451 ack_params
.mailbox_name
= mailbox_name
;
452 ack_params
.sync_point
= sync_point
;
453 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id
,
459 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
460 const IPC::Message
& message
) {
461 switch (message
.type()) {
462 case BrowserPluginHostMsg_BuffersSwappedACK::ID
:
463 case BrowserPluginHostMsg_DragStatusUpdate::ID
:
464 case BrowserPluginHostMsg_Go::ID
:
465 case BrowserPluginHostMsg_HandleInputEvent::ID
:
466 case BrowserPluginHostMsg_LockMouse_ACK::ID
:
467 case BrowserPluginHostMsg_NavigateGuest::ID
:
468 case BrowserPluginHostMsg_PluginDestroyed::ID
:
469 case BrowserPluginHostMsg_Reload::ID
:
470 case BrowserPluginHostMsg_ResizeGuest::ID
:
471 case BrowserPluginHostMsg_RespondPermission::ID
:
472 case BrowserPluginHostMsg_SetAutoSize::ID
:
473 case BrowserPluginHostMsg_SetFocus::ID
:
474 case BrowserPluginHostMsg_SetName::ID
:
475 case BrowserPluginHostMsg_SetVisibility::ID
:
476 case BrowserPluginHostMsg_Stop::ID
:
477 case BrowserPluginHostMsg_TerminateGuest::ID
:
478 case BrowserPluginHostMsg_UnlockMouse_ACK::ID
:
479 case BrowserPluginHostMsg_UpdateRect_ACK::ID
:
488 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message
& message
) {
490 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
491 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow
, OnCreateWindow
)
492 IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK
, OnHandleInputEventAck
)
493 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
494 OnHasTouchEventHandlers
)
495 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
497 #if defined(OS_MACOSX)
498 // MacOSX creates and populates platform-specific select drop-down menus
499 // whereas other platforms merely create a popup window that the guest
500 // renderer process paints inside.
501 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup
, OnShowPopup
)
503 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget
, OnShowWidget
)
504 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus
, OnTakeFocus
)
505 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnUnlockMouse
)
506 IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor
, OnUpdateDragCursor
)
507 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName
, OnUpdateFrameName
)
508 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnUpdateRect
)
509 IPC_MESSAGE_UNHANDLED(handled
= false)
510 IPC_END_MESSAGE_MAP()
514 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id
,
515 WebKit::WebDragStatus drag_status
,
516 const WebDropData
& drop_data
,
517 WebKit::WebDragOperationsMask mask
,
518 const gfx::Point
& location
) {
519 RenderViewHost
* host
= GetWebContents()->GetRenderViewHost();
520 switch (drag_status
) {
521 case WebKit::WebDragStatusEnter
:
522 host
->DragTargetDragEnter(drop_data
, location
, location
, mask
, 0);
524 case WebKit::WebDragStatusOver
:
525 host
->DragTargetDragOver(location
, location
, mask
, 0);
527 case WebKit::WebDragStatusLeave
:
528 host
->DragTargetDragLeave();
530 case WebKit::WebDragStatusDrop
:
531 host
->DragTargetDrop(location
, location
, 0);
533 case WebKit::WebDragStatusUnknown
:
538 void BrowserPluginGuest::OnGo(int instance_id
, int relative_index
) {
539 GetWebContents()->GetController().GoToOffset(relative_index
);
542 void BrowserPluginGuest::OnHandleInputEvent(
544 const gfx::Rect
& guest_window_rect
,
545 const WebKit::WebInputEvent
* event
) {
546 guest_window_rect_
= guest_window_rect
;
547 guest_screen_rect_
= guest_window_rect
;
548 guest_screen_rect_
.Offset(
549 embedder_web_contents_
->GetRenderViewHost()->GetView()->
550 GetViewBounds().OffsetFromOrigin());
551 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
552 GetWebContents()->GetRenderViewHost());
554 IPC::Message
* message
= NULL
;
556 // TODO(fsamuel): What should we do for keyboard_shortcut field?
557 if (event
->type
== WebKit::WebInputEvent::KeyDown
) {
558 CHECK_EQ(sizeof(WebKit::WebKeyboardEvent
), event
->size
);
559 WebKit::WebKeyboardEvent key_event
;
560 memcpy(&key_event
, event
, event
->size
);
561 key_event
.type
= WebKit::WebInputEvent::RawKeyDown
;
562 message
= new ViewMsg_HandleInputEvent(routing_id(), &key_event
, false);
564 message
= new ViewMsg_HandleInputEvent(routing_id(), event
, false);
568 guest_rvh
->StartHangMonitorTimeout(guest_hang_timeout_
);
571 void BrowserPluginGuest::OnLockMouse(bool user_gesture
,
572 bool last_unlocked_by_target
,
574 SendMessageToEmbedder(new BrowserPluginMsg_LockMouse(
575 embedder_routing_id(),
578 last_unlocked_by_target
,
582 void BrowserPluginGuest::OnLockMouseAck(int instance_id
, bool succeeded
) {
583 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded
));
585 mouse_locked_
= true;
588 void BrowserPluginGuest::OnNavigateGuest(
590 const std::string
& src
) {
592 // We do not load empty urls in web_contents.
593 // If a guest sets empty src attribute after it has navigated to some
594 // non-empty page, the action is considered no-op. This empty src navigation
595 // should never be sent to BrowserPluginGuest (browser process).
596 DCHECK(!src
.empty());
598 // As guests do not swap processes on navigation, only navigations to
599 // normal web URLs are supported. No protocol handlers are installed for
600 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
601 // can be granted to the guest process.
602 GetWebContents()->GetController().LoadURL(url
, Referrer(),
603 PAGE_TRANSITION_AUTO_TOPLEVEL
,
608 void BrowserPluginGuest::OnPluginDestroyed(int instance_id
) {
612 void BrowserPluginGuest::OnReload(int instance_id
) {
613 // TODO(fsamuel): Don't check for repost because we don't want to show
614 // Chromium's repost warning. We might want to implement a separate API
615 // for registering a callback if a repost is about to happen.
616 GetWebContents()->GetController().Reload(false);
619 void BrowserPluginGuest::OnResizeGuest(
621 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
622 // BrowserPlugin manages resize flow control itself and does not depend
623 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
624 // here. If we are setting the size for the first time before navigating then
625 // BrowserPluginGuest does not yet have a RenderViewHost.
626 if (GetWebContents()->GetRenderViewHost()) {
627 RenderWidgetHostImpl
* render_widget_host
=
628 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
629 render_widget_host
->ResetSizeAndRepaintPendingFlags();
631 if (!base::SharedMemory::IsHandleValid(params
.damage_buffer_handle
)) {
632 // Invalid damage buffer, so just resize the WebContents.
633 if (!params
.view_size
.IsEmpty())
634 GetWebContents()->GetView()->SizeContents(params
.view_size
);
637 SetDamageBuffer(params
);
638 GetWebContents()->GetView()->SizeContents(params
.view_size
);
640 Send(new ViewMsg_Repaint(routing_id(), params
.view_size
));
643 void BrowserPluginGuest::OnSetFocus(int instance_id
, bool focused
) {
644 if (focused_
== focused
)
647 Send(new ViewMsg_SetFocus(routing_id(), focused
));
650 void BrowserPluginGuest::OnSetName(int instance_id
, const std::string
& name
) {
654 Send(new ViewMsg_SetName(routing_id(), name
));
657 void BrowserPluginGuest::OnSetSize(
659 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
660 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
661 bool old_auto_size_enabled
= auto_size_enabled_
;
662 gfx::Size old_max_size
= max_auto_size_
;
663 gfx::Size old_min_size
= min_auto_size_
;
664 auto_size_enabled_
= auto_size_params
.enable
;
665 max_auto_size_
= auto_size_params
.max_size
;
666 min_auto_size_
= auto_size_params
.min_size
;
667 if (auto_size_enabled_
&& (!old_auto_size_enabled
||
668 (old_max_size
!= max_auto_size_
) ||
669 (old_min_size
!= min_auto_size_
))) {
670 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
671 min_auto_size_
, max_auto_size_
);
672 // TODO(fsamuel): If we're changing autosize parameters, then we force
673 // the guest to completely repaint itself, because BrowserPlugin has
674 // allocated a new damage buffer and expects a full frame of pixels.
675 // Ideally, we shouldn't need to do this because we shouldn't need to
676 // allocate a new damage buffer unless |max_auto_size_| has changed.
677 // However, even in that case, layout may not change and so we may
678 // not get a full frame worth of pixels.
679 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_
));
680 } else if (!auto_size_enabled_
&& old_auto_size_enabled
) {
681 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
682 resize_guest_params
.view_size
);
684 OnResizeGuest(instance_id_
, resize_guest_params
);
687 void BrowserPluginGuest::OnSetVisibility(int instance_id
, bool visible
) {
688 guest_visible_
= visible
;
689 if (embedder_visible_
&& guest_visible_
)
690 GetWebContents()->WasShown();
692 GetWebContents()->WasHidden();
695 void BrowserPluginGuest::OnStop(int instance_id
) {
696 GetWebContents()->Stop();
699 void BrowserPluginGuest::OnRespondPermission(
701 BrowserPluginPermissionType permission_type
,
704 if (permission_type
!= BrowserPluginPermissionTypeMedia
)
707 MediaStreamRequestsMap::iterator media_request_iter
=
708 media_requests_map_
.find(request_id
);
709 if (media_request_iter
== media_requests_map_
.end()) {
710 LOG(INFO
) << "Not a valid request ID.";
713 const content::MediaStreamRequest
& request
= media_request_iter
->second
.first
;
714 const content::MediaResponseCallback
& callback
=
715 media_request_iter
->second
.second
;
717 if (should_allow
&& embedder_web_contents_
) {
718 // Re-route the request to the embedder's WebContents; the guest gets the
719 // permission this way.
720 embedder_web_contents_
->RequestMediaAccessPermission(request
, callback
);
723 callback
.Run(content::MediaStreamDevices());
725 media_requests_map_
.erase(media_request_iter
);
728 void BrowserPluginGuest::OnSwapBuffersACK(int instance_id
,
731 const gpu::Mailbox
& mailbox_name
,
733 AcknowledgeBufferPresent(route_id
, gpu_host_id
, mailbox_name
, sync_point
);
735 // This is only relevant on MACOSX and WIN when threaded compositing
736 // is not enabled. In threaded mode, above ACK is sufficient.
737 #if defined(OS_MACOSX) || defined(OS_WIN)
738 RenderWidgetHostImpl
* render_widget_host
=
739 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
740 render_widget_host
->AcknowledgeSwapBuffersToRenderer();
741 #endif // defined(OS_MACOSX) || defined(OS_WIN)
744 void BrowserPluginGuest::OnTerminateGuest(int instance_id
) {
745 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Terminate"));
746 base::ProcessHandle process_handle
=
747 GetWebContents()->GetRenderProcessHost()->GetHandle();
749 base::KillProcess(process_handle
, RESULT_CODE_KILLED
, false);
752 void BrowserPluginGuest::OnUnlockMouse() {
753 SendMessageToEmbedder(new BrowserPluginMsg_UnlockMouse(embedder_routing_id(),
757 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id
) {
758 // mouse_locked_ could be false here if the lock attempt was cancelled due
759 // to window focus, or for various other reasons before the guest was informed
760 // of the lock's success.
762 Send(new ViewMsg_MouseLockLost(routing_id()));
763 mouse_locked_
= false;
766 void BrowserPluginGuest::OnUpdateRectACK(
768 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
769 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
770 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
771 OnSetSize(instance_id_
, auto_size_params
, resize_guest_params
);
774 void BrowserPluginGuest::OnCreateWindow(
775 const ViewHostMsg_CreateWindow_Params
& params
,
778 int64
* cloned_session_storage_namespace_id
) {
779 // TODO(fsamuel): We do not currently support window.open.
780 // See http://crbug.com/140316.
781 *route_id
= MSG_ROUTING_NONE
;
783 *cloned_session_storage_namespace_id
= 0l;
786 void BrowserPluginGuest::OnHandleInputEventAck(
787 WebKit::WebInputEvent::Type event_type
,
788 InputEventAckState ack_result
) {
789 RenderViewHostImpl
* guest_rvh
=
790 static_cast<RenderViewHostImpl
*>(GetWebContents()->GetRenderViewHost());
791 guest_rvh
->StopHangMonitorTimeout();
794 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept
) {
795 SendMessageToEmbedder(
796 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept
));
799 void BrowserPluginGuest::OnSetCursor(const WebCursor
& cursor
) {
800 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor
));
803 #if defined(OS_MACOSX)
804 void BrowserPluginGuest::OnShowPopup(
805 const ViewHostMsg_ShowPopup_Params
& params
) {
806 gfx::Rect
translated_bounds(params
.bounds
);
807 translated_bounds
.Offset(guest_window_rect_
.OffsetFromOrigin());
808 BrowserPluginPopupMenuHelper
popup_menu_helper(
809 embedder_web_contents_
->GetRenderViewHost(),
810 GetWebContents()->GetRenderViewHost());
811 popup_menu_helper
.ShowPopupMenu(translated_bounds
,
813 params
.item_font_size
,
814 params
.selected_item
,
816 params
.right_aligned
,
817 params
.allow_multiple_selection
);
821 void BrowserPluginGuest::OnShowWidget(int route_id
,
822 const gfx::Rect
& initial_pos
) {
823 gfx::Rect
screen_pos(initial_pos
);
824 screen_pos
.Offset(guest_screen_rect_
.OffsetFromOrigin());
825 GetWebContents()->ShowCreatedWidget(route_id
, screen_pos
);
828 void BrowserPluginGuest::OnTakeFocus(bool reverse
) {
829 SendMessageToEmbedder(
830 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse
));
833 void BrowserPluginGuest::OnUpdateDragCursor(
834 WebKit::WebDragOperation operation
) {
835 RenderViewHostImpl
* embedder_render_view_host
=
836 static_cast<RenderViewHostImpl
*>(
837 embedder_web_contents_
->GetRenderViewHost());
838 CHECK(embedder_render_view_host
);
839 RenderViewHostDelegateView
* view
=
840 embedder_render_view_host
->GetDelegate()->GetDelegateView();
842 view
->UpdateDragCursor(operation
);
845 void BrowserPluginGuest::OnUpdateFrameName(int frame_id
,
847 const std::string
& name
) {
852 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_
, name
));
855 void BrowserPluginGuest::RequestMediaAccessPermission(
856 WebContents
* web_contents
,
857 const content::MediaStreamRequest
& request
,
858 const content::MediaResponseCallback
& callback
) {
859 if (media_requests_map_
.size() >= kNumMaxOutstandingMediaRequests
) {
860 // Deny the media request.
861 callback
.Run(content::MediaStreamDevices());
864 int request_id
= current_media_access_request_id_
++;
865 media_requests_map_
.insert(
866 std::make_pair(request_id
,
867 std::make_pair(request
, callback
)));
869 base::DictionaryValue request_info
;
871 browser_plugin::kURL
,
872 base::Value::CreateStringValue(request
.security_origin
.spec()));
873 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
874 instance_id(), BrowserPluginPermissionTypeMedia
,
875 request_id
, request_info
));
878 void BrowserPluginGuest::OnUpdateRect(
879 const ViewHostMsg_UpdateRect_Params
& params
) {
881 BrowserPluginMsg_UpdateRect_Params relay_params
;
882 relay_params
.view_size
= params
.view_size
;
883 relay_params
.scale_factor
= params
.scale_factor
;
884 relay_params
.is_resize_ack
= ViewHostMsg_UpdateRect_Flags::is_resize_ack(
886 relay_params
.needs_ack
= params
.needs_ack
;
888 // HW accelerated case, acknowledge resize only
889 if (!params
.needs_ack
|| !damage_buffer_
) {
890 relay_params
.damage_buffer_sequence_id
= 0;
891 SendMessageToEmbedder(
892 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params
));
896 // Only copy damage if the guest is in autosize mode and the guest's view size
897 // is less than the maximum size or the guest's view size is equal to the
898 // damage buffer's size and the guest's scale factor is equal to the damage
899 // buffer's scale factor.
900 // The scaling change can happen due to asynchronous updates of the DPI on a
901 // resolution change.
902 if (((auto_size_enabled_
&& InAutoSizeBounds(params
.view_size
)) ||
903 (params
.view_size
.width() == damage_view_size().width() &&
904 params
.view_size
.height() == damage_view_size().height())) &&
905 params
.scale_factor
== damage_buffer_scale_factor()) {
906 TransportDIB
* dib
= GetWebContents()->GetRenderProcessHost()->
907 GetTransportDIB(params
.bitmap
);
909 size_t guest_damage_buffer_size
=
911 params
.bitmap_rect
.width() *
912 params
.bitmap_rect
.height() * 4;
916 size_t embedder_damage_buffer_size
= damage_buffer_size_
;
917 void* guest_memory
= dib
->memory();
918 void* embedder_memory
= damage_buffer_
->memory();
919 size_t size
= std::min(guest_damage_buffer_size
,
920 embedder_damage_buffer_size
);
921 memcpy(embedder_memory
, guest_memory
, size
);
924 relay_params
.damage_buffer_sequence_id
= damage_buffer_sequence_id_
;
925 relay_params
.bitmap_rect
= params
.bitmap_rect
;
926 relay_params
.scroll_delta
= params
.scroll_delta
;
927 relay_params
.scroll_rect
= params
.scroll_rect
;
928 relay_params
.copy_rects
= params
.copy_rects
;
930 SendMessageToEmbedder(
931 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params
));
934 } // namespace content