Use gpu::Mailbox in IPCs instead of std::string
[chromium-blink-merge.git] / content / browser / browser_plugin / browser_plugin_guest.cc
bloba649a5f9654478d41379e66623626642d1770909
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"
7 #include <algorithm>
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"
45 #endif
47 namespace content {
49 // static
50 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
52 namespace {
53 const size_t kNumMaxOutstandingMediaRequests = 1024;
56 BrowserPluginGuest::BrowserPluginGuest(
57 int instance_id,
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),
66 guest_hang_timeout_(
67 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
68 focused_(params.focused),
69 mouse_locked_(false),
70 guest_visible_(params.visible),
71 embedder_visible_(true),
72 name_(params.name),
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) {
77 DCHECK(web_contents);
78 web_contents->SetDelegate(this);
79 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
80 GetWebContents());
83 void BrowserPluginGuest::Destroy() {
84 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_);
85 delete GetWebContents();
88 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
89 const IPC::Message& message) {
90 bool handled = true;
91 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
92 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
93 OnSwapBuffersACK)
94 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
95 OnDragStatusUpdate)
96 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go, OnGo)
97 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
98 OnHandleInputEvent)
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,
105 OnRespondPermission)
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()
116 return handled;
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
134 // focus.
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
152 // visible.
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_,
170 guest_routing_id));
172 if (!params.src.empty())
173 OnNavigateGuest(instance_id_, params.src);
175 GetContentClient()->browser()->GuestWebContentsCreated(
176 GetWebContents(), embedder_web_contents_);
179 BrowserPluginGuest::~BrowserPluginGuest() {
182 // static
183 BrowserPluginGuest* BrowserPluginGuest::Create(
184 int instance_id,
185 WebContentsImpl* web_contents,
186 const BrowserPluginHostMsg_CreateGuest_Params& params) {
187 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
188 if (factory_) {
189 return factory_->CreateBrowserPluginGuest(instance_id,
190 web_contents,
191 params);
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) {
207 switch (type) {
208 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
209 DCHECK_EQ(Source<WebContents>(source).ptr(), GetWebContents());
210 ResourceRedirectDetails* resource_redirect_details =
211 Details<ResourceRedirectDetails>(details).ptr();
212 bool is_top_level =
213 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
214 LoadRedirect(resource_redirect_details->url,
215 resource_redirect_details->new_url,
216 is_top_level);
217 break;
219 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
220 DCHECK_EQ(Source<WebContents>(source).ptr(), embedder_web_contents_);
221 embedder_visible_ = *Details<bool>(details).ptr();
222 UpdateVisibility();
223 break;
225 case NOTIFICATION_RENDER_VIEW_HOST_DELETED: {
226 Destroy();
227 break;
229 default:
230 NOTREACHED() << "Unexpected notification sent.";
231 break;
235 bool BrowserPluginGuest::CanDownload(RenderViewHost* render_view_host,
236 int request_id,
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.
242 return false;
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).
250 return true;
253 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
254 int process_id =
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) {
262 int process_id =
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.
277 return false;
280 WebContentsImpl* BrowserPluginGuest::GetWebContents() {
281 return static_cast<WebContentsImpl*>(web_contents());
284 base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
285 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
286 #if defined(OS_WIN)
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));
294 #endif
295 if (!shared_buf->Map(params.damage_buffer_size)) {
296 NOTREACHED();
297 return NULL;
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();
318 return screen_pos;
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(
331 int64 frame_id,
332 int64 parent_frame_id,
333 bool is_main_frame,
334 const GURL& validated_url,
335 bool is_error_page,
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(),
341 validated_url,
342 is_main_frame));
345 void BrowserPluginGuest::DidFailProvisionalLoad(
346 int64 frame_id,
347 bool is_main_frame,
348 const GURL& validated_url,
349 int error_code,
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(),
358 validated_url,
359 is_main_frame,
360 error_type));
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(
369 const GURL& old_url,
370 const GURL& new_url,
371 bool is_top_level) {
372 SendMessageToEmbedder(
373 new BrowserPluginMsg_LoadRedirect(instance_id(),
374 old_url,
375 new_url,
376 is_top_level));
379 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
380 int64 frame_id,
381 bool is_main_frame,
382 const GURL& url,
383 PageTransition transition_type,
384 RenderViewHost* render_view_host) {
385 // Inform its embedder of the updated URL.
386 BrowserPluginMsg_LoadCommit_Params params;
387 params.url = url;
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();
393 params.entry_count =
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(); "
405 "});";
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_));
415 UpdateVisibility();
416 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
417 if (auto_size_enabled_)
418 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
419 else
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));
429 switch (status) {
430 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
431 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
432 break;
433 case base::TERMINATION_STATUS_PROCESS_CRASHED:
434 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
435 break;
436 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
437 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
438 break;
439 default:
440 break;
444 // static
445 void BrowserPluginGuest::AcknowledgeBufferPresent(
446 int route_id,
447 int gpu_host_id,
448 const gpu::Mailbox& mailbox_name,
449 uint32 sync_point) {
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,
454 gpu_host_id,
455 ack_params);
458 // static
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:
480 return true;
481 default:
482 break;
484 return false;
488 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
489 bool handled = true;
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)
502 #endif
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()
511 return handled;
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);
523 break;
524 case WebKit::WebDragStatusOver:
525 host->DragTargetDragOver(location, location, mask, 0);
526 break;
527 case WebKit::WebDragStatusLeave:
528 host->DragTargetDragLeave();
529 break;
530 case WebKit::WebDragStatusDrop:
531 host->DragTargetDrop(location, location, 0);
532 break;
533 case WebKit::WebDragStatusUnknown:
534 NOTREACHED();
538 void BrowserPluginGuest::OnGo(int instance_id, int relative_index) {
539 GetWebContents()->GetController().GoToOffset(relative_index);
542 void BrowserPluginGuest::OnHandleInputEvent(
543 int instance_id,
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);
563 } else {
564 message = new ViewMsg_HandleInputEvent(routing_id(), event, false);
567 Send(message);
568 guest_rvh->StartHangMonitorTimeout(guest_hang_timeout_);
571 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
572 bool last_unlocked_by_target,
573 bool privileged) {
574 SendMessageToEmbedder(new BrowserPluginMsg_LockMouse(
575 embedder_routing_id(),
576 instance_id(),
577 user_gesture,
578 last_unlocked_by_target,
579 privileged));
582 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
583 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
584 if (succeeded)
585 mouse_locked_ = true;
588 void BrowserPluginGuest::OnNavigateGuest(
589 int instance_id,
590 const std::string& src) {
591 GURL url(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());
597 if (!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,
604 std::string());
608 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
609 Destroy();
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(
620 int instance_id,
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);
635 return;
637 SetDamageBuffer(params);
638 GetWebContents()->GetView()->SizeContents(params.view_size);
639 if (params.repaint)
640 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
643 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
644 if (focused_ == focused)
645 return;
646 focused_ = focused;
647 Send(new ViewMsg_SetFocus(routing_id(), focused));
650 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
651 if (name == name_)
652 return;
653 name_ = name;
654 Send(new ViewMsg_SetName(routing_id(), name));
657 void BrowserPluginGuest::OnSetSize(
658 int instance_id,
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();
691 else
692 GetWebContents()->WasHidden();
695 void BrowserPluginGuest::OnStop(int instance_id) {
696 GetWebContents()->Stop();
699 void BrowserPluginGuest::OnRespondPermission(
700 int /*instance_id*/,
701 BrowserPluginPermissionType permission_type,
702 int request_id,
703 bool should_allow) {
704 if (permission_type != BrowserPluginPermissionTypeMedia)
705 return;
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.";
711 return;
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);
721 } else {
722 // Deny the request.
723 callback.Run(content::MediaStreamDevices());
725 media_requests_map_.erase(media_request_iter);
728 void BrowserPluginGuest::OnSwapBuffersACK(int instance_id,
729 int route_id,
730 int gpu_host_id,
731 const gpu::Mailbox& mailbox_name,
732 uint32 sync_point) {
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();
748 if (process_handle)
749 base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
752 void BrowserPluginGuest::OnUnlockMouse() {
753 SendMessageToEmbedder(new BrowserPluginMsg_UnlockMouse(embedder_routing_id(),
754 instance_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.
761 if (mouse_locked_)
762 Send(new ViewMsg_MouseLockLost(routing_id()));
763 mouse_locked_ = false;
766 void BrowserPluginGuest::OnUpdateRectACK(
767 int instance_id,
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,
776 int* route_id,
777 int* surface_id,
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;
782 *surface_id = 0;
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,
812 params.item_height,
813 params.item_font_size,
814 params.selected_item,
815 params.popup_items,
816 params.right_aligned,
817 params.allow_multiple_selection);
819 #endif
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();
841 if (view)
842 view->UpdateDragCursor(operation);
845 void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
846 bool is_top_level,
847 const std::string& name) {
848 if (!is_top_level)
849 return;
851 name_ = 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());
862 return;
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;
870 request_info.Set(
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(
885 params.flags);
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));
893 return;
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);
908 if (dib) {
909 size_t guest_damage_buffer_size =
910 #if defined(OS_WIN)
911 params.bitmap_rect.width() *
912 params.bitmap_rect.height() * 4;
913 #else
914 dib->size();
915 #endif
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