• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/browser/browser_plugin/browser_plugin_guest.h"
6 
7 #include <algorithm>
8 
9 #include "base/message_loop/message_loop.h"
10 #include "base/pickle.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/frame_host/render_widget_host_view_guest.h"
17 #include "content/browser/loader/resource_dispatcher_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_base.h"
21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/browser/web_contents/web_contents_view_guest.h"
23 #include "content/common/browser_plugin/browser_plugin_constants.h"
24 #include "content/common/browser_plugin/browser_plugin_messages.h"
25 #include "content/common/content_constants_internal.h"
26 #include "content/common/drag_messages.h"
27 #include "content/common/frame_messages.h"
28 #include "content/common/host_shared_bitmap_manager.h"
29 #include "content/common/input_messages.h"
30 #include "content/common/view_messages.h"
31 #include "content/public/browser/browser_context.h"
32 #include "content/public/browser/browser_plugin_guest_manager.h"
33 #include "content/public/browser/content_browser_client.h"
34 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/user_metrics.h"
36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/common/drop_data.h"
38 #include "ui/gfx/geometry/size_conversions.h"
39 
40 #if defined(OS_MACOSX)
41 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
42 #endif
43 
44 namespace content {
45 
46 class BrowserPluginGuest::EmbedderWebContentsObserver
47     : public WebContentsObserver {
48  public:
EmbedderWebContentsObserver(BrowserPluginGuest * guest)49   explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
50       : WebContentsObserver(guest->embedder_web_contents()),
51         browser_plugin_guest_(guest) {
52   }
53 
~EmbedderWebContentsObserver()54   virtual ~EmbedderWebContentsObserver() {
55   }
56 
57   // WebContentsObserver implementation.
WasShown()58   virtual void WasShown() OVERRIDE {
59     browser_plugin_guest_->EmbedderVisibilityChanged(true);
60   }
61 
WasHidden()62   virtual void WasHidden() OVERRIDE {
63     browser_plugin_guest_->EmbedderVisibilityChanged(false);
64   }
65 
66  private:
67   BrowserPluginGuest* browser_plugin_guest_;
68 
69   DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
70 };
71 
BrowserPluginGuest(bool has_render_view,WebContentsImpl * web_contents,BrowserPluginGuestDelegate * delegate)72 BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
73                                        WebContentsImpl* web_contents,
74                                        BrowserPluginGuestDelegate* delegate)
75     : WebContentsObserver(web_contents),
76       embedder_web_contents_(NULL),
77       browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
78       guest_device_scale_factor_(1.0f),
79       focused_(false),
80       mouse_locked_(false),
81       pending_lock_request_(false),
82       guest_visible_(false),
83       embedder_visible_(true),
84       copy_request_id_(0),
85       has_render_view_(has_render_view),
86       is_in_destruction_(false),
87       last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
88       last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
89       last_can_compose_inline_(true),
90       delegate_(delegate),
91       weak_ptr_factory_(this) {
92   DCHECK(web_contents);
93   DCHECK(delegate);
94   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
95   web_contents->SetBrowserPluginGuest(this);
96   delegate->RegisterDestructionCallback(
97       base::Bind(&BrowserPluginGuest::WillDestroy, AsWeakPtr()));
98 }
99 
WillDestroy()100 void BrowserPluginGuest::WillDestroy() {
101   is_in_destruction_ = true;
102   embedder_web_contents_ = NULL;
103 }
104 
AsWeakPtr()105 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
106   return weak_ptr_factory_.GetWeakPtr();
107 }
108 
SetFocus(RenderWidgetHost * rwh,bool focused)109 void BrowserPluginGuest::SetFocus(RenderWidgetHost* rwh, bool focused) {
110   focused_ = focused;
111   if (!rwh)
112     return;
113 
114   rwh->Send(new InputMsg_SetFocus(rwh->GetRoutingID(), focused));
115   if (!focused && mouse_locked_)
116     OnUnlockMouse();
117 
118   // Restore the last seen state of text input to the view.
119   RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
120       rwh->GetView());
121   if (rwhv) {
122     rwhv->TextInputTypeChanged(last_text_input_type_, last_input_mode_,
123                                last_can_compose_inline_);
124   }
125 }
126 
LockMouse(bool allowed)127 bool BrowserPluginGuest::LockMouse(bool allowed) {
128   if (!attached() || (mouse_locked_ == allowed))
129     return false;
130 
131   return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
132 }
133 
Destroy()134 void BrowserPluginGuest::Destroy() {
135   delegate_->Destroy();
136 }
137 
CreateNewGuestWindow(const WebContents::CreateParams & params)138 WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow(
139     const WebContents::CreateParams& params) {
140   WebContentsImpl* new_contents =
141       static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params));
142   DCHECK(new_contents);
143   return new_contents;
144 }
145 
OnMessageReceivedFromEmbedder(const IPC::Message & message)146 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
147     const IPC::Message& message) {
148   RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
149       web_contents()->GetRenderWidgetHostView());
150   if (rwhv &&
151       rwhv->OnMessageReceivedFromEmbedder(
152           message,
153           static_cast<RenderViewHostImpl*>(
154               embedder_web_contents()->GetRenderViewHost()))) {
155     return true;
156   }
157 
158   bool handled = true;
159   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
160     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
161                         OnCompositorFrameSwappedACK)
162     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
163                         OnCopyFromCompositingSurfaceAck)
164     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
165                         OnDragStatusUpdate)
166     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
167                         OnExecuteEditCommand)
168     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
169                         OnExtendSelectionAndDelete)
170     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
171                         OnImeConfirmComposition)
172     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
173                         OnImeSetComposition)
174     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
175     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
176     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
177                         OnReclaimCompositorResources)
178     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
179     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
180                         OnSetEditCommandsForNextKeyEvent)
181     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
182     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
183     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
184     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
185     IPC_MESSAGE_UNHANDLED(handled = false)
186   IPC_END_MESSAGE_MAP()
187   return handled;
188 }
189 
Initialize(int browser_plugin_instance_id,const BrowserPluginHostMsg_Attach_Params & params,WebContentsImpl * embedder_web_contents)190 void BrowserPluginGuest::Initialize(
191     int browser_plugin_instance_id,
192     const BrowserPluginHostMsg_Attach_Params& params,
193     WebContentsImpl* embedder_web_contents) {
194   browser_plugin_instance_id_ = browser_plugin_instance_id;
195   focused_ = params.focused;
196   guest_visible_ = params.visible;
197   guest_window_rect_ = gfx::Rect(params.origin,
198                                  params.resize_guest_params.view_size);
199 
200   // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
201   // be attached.
202   embedder_web_contents_ = embedder_web_contents;
203 
204   WebContentsViewGuest* new_view =
205       static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
206   new_view->OnGuestInitialized(embedder_web_contents->GetView());
207 
208   RendererPreferences* renderer_prefs =
209       GetWebContents()->GetMutableRendererPrefs();
210   std::string guest_user_agent_override = renderer_prefs->user_agent_override;
211   // Copy renderer preferences (and nothing else) from the embedder's
212   // WebContents to the guest.
213   //
214   // For GTK and Aura this is necessary to get proper renderer configuration
215   // values for caret blinking interval, colors related to selection and
216   // focus.
217   *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
218   renderer_prefs->user_agent_override = guest_user_agent_override;
219 
220   // We would like the guest to report changes to frame names so that we can
221   // update the BrowserPlugin's corresponding 'name' attribute.
222   // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
223   renderer_prefs->report_frame_name_changes = true;
224   // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
225   // navigations still continue to function inside the app.
226   renderer_prefs->browser_handles_all_top_level_requests = false;
227   // Disable "client blocked" error page for browser plugin.
228   renderer_prefs->disable_client_blocked_error_page = true;
229 
230   embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
231 
232   OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params);
233 
234   // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
235   // be reset again the next time preferences are updated.
236   WebPreferences prefs =
237       GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
238   prefs.navigate_on_drag_drop = false;
239   GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
240 
241   // Enable input method for guest if it's enabled for the embedder.
242   if (static_cast<RenderViewHostImpl*>(
243       embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
244     RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
245         GetWebContents()->GetRenderViewHost());
246     guest_rvh->SetInputMethodActive(true);
247   }
248 
249   // Inform the embedder of the guest's attachment.
250   SendMessageToEmbedder(
251       new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_));
252 }
253 
~BrowserPluginGuest()254 BrowserPluginGuest::~BrowserPluginGuest() {
255 }
256 
257 // static
Create(WebContentsImpl * web_contents,BrowserPluginGuestDelegate * delegate)258 BrowserPluginGuest* BrowserPluginGuest::Create(
259     WebContentsImpl* web_contents,
260     BrowserPluginGuestDelegate* delegate) {
261   return new BrowserPluginGuest(
262       web_contents->opener() != NULL, web_contents, delegate);
263 }
264 
265 // static
IsGuest(WebContentsImpl * web_contents)266 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
267   return web_contents && web_contents->GetBrowserPluginGuest();
268 }
269 
270 // static
IsGuest(RenderViewHostImpl * render_view_host)271 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
272   return render_view_host && IsGuest(
273       static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
274           render_view_host)));
275 }
276 
GetEmbedderRenderWidgetHostView()277 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
278   if (!attached())
279     return NULL;
280   return embedder_web_contents_->GetRenderWidgetHostView();
281 }
282 
UpdateVisibility()283 void BrowserPluginGuest::UpdateVisibility() {
284   OnSetVisibility(browser_plugin_instance_id(), visible());
285 }
286 
CopyFromCompositingSurface(gfx::Rect src_subrect,gfx::Size dst_size,const base::Callback<void (bool,const SkBitmap &)> & callback)287 void BrowserPluginGuest::CopyFromCompositingSurface(
288       gfx::Rect src_subrect,
289       gfx::Size dst_size,
290       const base::Callback<void(bool, const SkBitmap&)>& callback) {
291   copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
292   SendMessageToEmbedder(
293       new BrowserPluginMsg_CopyFromCompositingSurface(
294           browser_plugin_instance_id(),
295           copy_request_id_,
296           src_subrect,
297           dst_size));
298 }
299 
300 BrowserPluginGuestManager*
GetBrowserPluginGuestManager() const301 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
302   return GetWebContents()->GetBrowserContext()->GetGuestManager();
303 }
304 
EmbedderVisibilityChanged(bool visible)305 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
306   embedder_visible_ = visible;
307   UpdateVisibility();
308 }
309 
PointerLockPermissionResponse(bool allow)310 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
311   SendMessageToEmbedder(
312       new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow));
313 }
314 
SwapCompositorFrame(uint32 output_surface_id,int host_process_id,int host_routing_id,scoped_ptr<cc::CompositorFrame> frame)315 void BrowserPluginGuest::SwapCompositorFrame(
316     uint32 output_surface_id,
317     int host_process_id,
318     int host_routing_id,
319     scoped_ptr<cc::CompositorFrame> frame) {
320   cc::RenderPass* root_pass =
321       frame->delegated_frame_data->render_pass_list.back();
322   gfx::Size view_size(gfx::ToFlooredSize(gfx::ScaleSize(
323       root_pass->output_rect.size(),
324       1.0f / frame->metadata.device_scale_factor)));
325 
326   if (last_seen_view_size_ != view_size) {
327     delegate_->GuestSizeChanged(last_seen_view_size_, view_size);
328     last_seen_view_size_ = view_size;
329   }
330 
331   FrameMsg_CompositorFrameSwapped_Params guest_params;
332   frame->AssignTo(&guest_params.frame);
333   guest_params.output_surface_id = output_surface_id;
334   guest_params.producing_route_id = host_routing_id;
335   guest_params.producing_host_id = host_process_id;
336 
337   SendMessageToEmbedder(
338       new BrowserPluginMsg_CompositorFrameSwapped(
339           browser_plugin_instance_id(), guest_params));
340 }
341 
SetContentsOpaque(bool opaque)342 void BrowserPluginGuest::SetContentsOpaque(bool opaque) {
343   SendMessageToEmbedder(
344       new BrowserPluginMsg_SetContentsOpaque(
345           browser_plugin_instance_id(), opaque));
346 }
347 
GetWebContents() const348 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
349   return static_cast<WebContentsImpl*>(web_contents());
350 }
351 
GetScreenCoordinates(const gfx::Point & relative_position) const352 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
353     const gfx::Point& relative_position) const {
354   if (!attached())
355     return relative_position;
356 
357   gfx::Point screen_pos(relative_position);
358   screen_pos += guest_window_rect_.OffsetFromOrigin();
359   if (embedder_web_contents()->GetBrowserPluginGuest()) {
360      BrowserPluginGuest* embedder_guest =
361         embedder_web_contents()->GetBrowserPluginGuest();
362      screen_pos += embedder_guest->guest_window_rect_.OffsetFromOrigin();
363   }
364   return screen_pos;
365 }
366 
SendMessageToEmbedder(IPC::Message * msg)367 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
368   if (!attached()) {
369     // Some pages such as data URLs, javascript URLs, and about:blank
370     // do not load external resources and so they load prior to attachment.
371     // As a result, we must save all these IPCs until attachment and then
372     // forward them so that the embedder gets a chance to see and process
373     // the load events.
374     pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
375     return;
376   }
377   msg->set_routing_id(embedder_web_contents_->GetRoutingID());
378   embedder_web_contents_->Send(msg);
379 }
380 
DragSourceEndedAt(int client_x,int client_y,int screen_x,int screen_y,blink::WebDragOperation operation)381 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
382     int screen_x, int screen_y, blink::WebDragOperation operation) {
383   web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
384       screen_x, screen_y, operation);
385 }
386 
EndSystemDrag()387 void BrowserPluginGuest::EndSystemDrag() {
388   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
389       GetWebContents()->GetRenderViewHost());
390   guest_rvh->DragSourceSystemDragEnded();
391 }
392 
SendQueuedMessages()393 void BrowserPluginGuest::SendQueuedMessages() {
394   if (!attached())
395     return;
396 
397   while (!pending_messages_.empty()) {
398     linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
399     pending_messages_.pop_front();
400     SendMessageToEmbedder(message_ptr.release());
401   }
402 }
403 
DidCommitProvisionalLoadForFrame(RenderFrameHost * render_frame_host,const GURL & url,ui::PageTransition transition_type)404 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
405     RenderFrameHost* render_frame_host,
406     const GURL& url,
407     ui::PageTransition transition_type) {
408   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
409 }
410 
RenderViewReady()411 void BrowserPluginGuest::RenderViewReady() {
412   RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
413   // TODO(fsamuel): Investigate whether it's possible to update state earlier
414   // here (see http://crbug.com/158151).
415   Send(new InputMsg_SetFocus(routing_id(), focused_));
416   UpdateVisibility();
417 
418   RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
419       base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
420 }
421 
RenderProcessGone(base::TerminationStatus status)422 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
423   SendMessageToEmbedder(
424       new BrowserPluginMsg_GuestGone(browser_plugin_instance_id()));
425   switch (status) {
426     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
427       RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
428       break;
429     case base::TERMINATION_STATUS_PROCESS_CRASHED:
430       RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
431       break;
432     case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
433       RecordAction(
434           base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
435       break;
436     default:
437       break;
438   }
439 }
440 
441 // static
ShouldForwardToBrowserPluginGuest(const IPC::Message & message)442 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
443     const IPC::Message& message) {
444   switch (message.type()) {
445     case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
446     case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
447     case BrowserPluginHostMsg_DragStatusUpdate::ID:
448     case BrowserPluginHostMsg_ExecuteEditCommand::ID:
449     case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
450     case BrowserPluginHostMsg_HandleInputEvent::ID:
451     case BrowserPluginHostMsg_ImeConfirmComposition::ID:
452     case BrowserPluginHostMsg_ImeSetComposition::ID:
453     case BrowserPluginHostMsg_LockMouse_ACK::ID:
454     case BrowserPluginHostMsg_PluginDestroyed::ID:
455     case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
456     case BrowserPluginHostMsg_ResizeGuest::ID:
457     case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
458     case BrowserPluginHostMsg_SetFocus::ID:
459     case BrowserPluginHostMsg_SetVisibility::ID:
460     case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
461     case BrowserPluginHostMsg_UpdateGeometry::ID:
462       return true;
463     default:
464       return false;
465   }
466 }
467 
OnMessageReceived(const IPC::Message & message)468 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
469   bool handled = true;
470   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
471     IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
472                         OnImeCancelComposition)
473 #if defined(OS_MACOSX) || defined(USE_AURA)
474     IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
475                         OnImeCompositionRangeChanged)
476 #endif
477     IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
478                         OnHasTouchEventHandlers)
479     IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
480     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
481     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
482     IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
483                         OnTextInputTypeChanged)
484     IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
485     IPC_MESSAGE_UNHANDLED(handled = false)
486   IPC_END_MESSAGE_MAP()
487   return handled;
488 }
489 
OnMessageReceived(const IPC::Message & message,RenderFrameHost * render_frame_host)490 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message,
491                                            RenderFrameHost* render_frame_host) {
492   // This will eventually be the home for more IPC handlers that depend on
493   // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't
494   // compile if there are no handlers for a platform. So we have both #if guards
495   // around the whole thing (unfortunate but temporary), and #if guards where
496   // they belong, only around the one IPC handler. TODO(avi): Move more of the
497   // frame-based handlers to this function and remove the outer #if layer.
498 #if defined(OS_MACOSX)
499   bool handled = true;
500   IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message,
501                                    render_frame_host)
502 #if defined(OS_MACOSX)
503     // MacOS X creates and populates platform-specific select drop-down menus
504     // whereas other platforms merely create a popup window that the guest
505     // renderer process paints inside.
506     IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
507 #endif
508     IPC_MESSAGE_UNHANDLED(handled = false)
509   IPC_END_MESSAGE_MAP()
510   return handled;
511 #else
512   return false;
513 #endif
514 }
515 
Attach(int browser_plugin_instance_id,WebContentsImpl * embedder_web_contents,const BrowserPluginHostMsg_Attach_Params & params)516 void BrowserPluginGuest::Attach(
517     int browser_plugin_instance_id,
518     WebContentsImpl* embedder_web_contents,
519     const BrowserPluginHostMsg_Attach_Params& params) {
520   if (attached())
521     return;
522 
523   delegate_->WillAttach(embedder_web_contents, browser_plugin_instance_id);
524 
525   // If a RenderView has already been created for this new window, then we need
526   // to initialize the browser-side state now so that the RenderFrameHostManager
527   // does not create a new RenderView on navigation.
528   if (has_render_view_) {
529     static_cast<RenderViewHostImpl*>(
530         GetWebContents()->GetRenderViewHost())->Init();
531     WebContentsViewGuest* new_view =
532         static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
533     new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
534   }
535 
536   Initialize(browser_plugin_instance_id, params, embedder_web_contents);
537 
538   SendQueuedMessages();
539 
540   // Create a swapped out RenderView for the guest in the embedder render
541   // process, so that the embedder can access the guest's window object.
542   int guest_routing_id =
543       GetWebContents()->CreateSwappedOutRenderView(
544           embedder_web_contents_->GetSiteInstance());
545 
546   delegate_->DidAttach(guest_routing_id);
547 
548   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
549 }
550 
OnCompositorFrameSwappedACK(int browser_plugin_instance_id,const FrameHostMsg_CompositorFrameSwappedACK_Params & params)551 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
552     int browser_plugin_instance_id,
553     const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
554   RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
555                                                    params.output_surface_id,
556                                                    params.producing_host_id,
557                                                    params.ack);
558 }
559 
OnDragStatusUpdate(int browser_plugin_instance_id,blink::WebDragStatus drag_status,const DropData & drop_data,blink::WebDragOperationsMask mask,const gfx::Point & location)560 void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
561                                             blink::WebDragStatus drag_status,
562                                             const DropData& drop_data,
563                                             blink::WebDragOperationsMask mask,
564                                             const gfx::Point& location) {
565   RenderViewHost* host = GetWebContents()->GetRenderViewHost();
566   switch (drag_status) {
567     case blink::WebDragStatusEnter:
568       embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
569           this);
570       host->DragTargetDragEnter(drop_data, location, location, mask, 0);
571       break;
572     case blink::WebDragStatusOver:
573       host->DragTargetDragOver(location, location, mask, 0);
574       break;
575     case blink::WebDragStatusLeave:
576       embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
577       host->DragTargetDragLeave();
578       break;
579     case blink::WebDragStatusDrop:
580       host->DragTargetDrop(location, location, 0);
581       EndSystemDrag();
582       break;
583     case blink::WebDragStatusUnknown:
584       NOTREACHED();
585   }
586 }
587 
OnExecuteEditCommand(int browser_plugin_instance_id,const std::string & name)588 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
589                                               const std::string& name) {
590   Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
591 }
592 
OnImeSetComposition(int browser_plugin_instance_id,const std::string & text,const std::vector<blink::WebCompositionUnderline> & underlines,int selection_start,int selection_end)593 void BrowserPluginGuest::OnImeSetComposition(
594     int browser_plugin_instance_id,
595     const std::string& text,
596     const std::vector<blink::WebCompositionUnderline>& underlines,
597     int selection_start,
598     int selection_end) {
599   Send(new InputMsg_ImeSetComposition(routing_id(),
600                                       base::UTF8ToUTF16(text), underlines,
601                                       selection_start, selection_end));
602 }
603 
OnImeConfirmComposition(int browser_plugin_instance_id,const std::string & text,bool keep_selection)604 void BrowserPluginGuest::OnImeConfirmComposition(
605     int browser_plugin_instance_id,
606     const std::string& text,
607     bool keep_selection) {
608   Send(new InputMsg_ImeConfirmComposition(routing_id(),
609                                           base::UTF8ToUTF16(text),
610                                           gfx::Range::InvalidRange(),
611                                           keep_selection));
612 }
613 
OnExtendSelectionAndDelete(int browser_plugin_instance_id,int before,int after)614 void BrowserPluginGuest::OnExtendSelectionAndDelete(
615     int browser_plugin_instance_id,
616     int before,
617     int after) {
618   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
619       web_contents()->GetFocusedFrame());
620   if (rfh)
621     rfh->ExtendSelectionAndDelete(before, after);
622 }
623 
OnReclaimCompositorResources(int browser_plugin_instance_id,const FrameHostMsg_ReclaimCompositorResources_Params & params)624 void BrowserPluginGuest::OnReclaimCompositorResources(
625     int browser_plugin_instance_id,
626     const FrameHostMsg_ReclaimCompositorResources_Params& params) {
627   RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
628                                                        params.output_surface_id,
629                                                        params.renderer_host_id,
630                                                        params.ack);
631 }
632 
OnLockMouse(bool user_gesture,bool last_unlocked_by_target,bool privileged)633 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
634                                      bool last_unlocked_by_target,
635                                      bool privileged) {
636   if (pending_lock_request_) {
637     // Immediately reject the lock because only one pointerLock may be active
638     // at a time.
639     Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
640     return;
641   }
642 
643   pending_lock_request_ = true;
644 
645   delegate_->RequestPointerLockPermission(
646       user_gesture,
647       last_unlocked_by_target,
648       base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
649                  weak_ptr_factory_.GetWeakPtr()));
650 }
651 
OnLockMouseAck(int browser_plugin_instance_id,bool succeeded)652 void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
653                                         bool succeeded) {
654   Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
655   pending_lock_request_ = false;
656   if (succeeded)
657     mouse_locked_ = true;
658 }
659 
OnPluginDestroyed(int browser_plugin_instance_id)660 void BrowserPluginGuest::OnPluginDestroyed(int browser_plugin_instance_id) {
661   Destroy();
662 }
663 
OnResizeGuest(int browser_plugin_instance_id,const BrowserPluginHostMsg_ResizeGuest_Params & params)664 void BrowserPluginGuest::OnResizeGuest(
665     int browser_plugin_instance_id,
666     const BrowserPluginHostMsg_ResizeGuest_Params& params) {
667   // If we are setting the size for the first time before navigating then
668   // BrowserPluginGuest does not yet have a RenderViewHost.
669   if (guest_device_scale_factor_ != params.scale_factor &&
670       GetWebContents()->GetRenderViewHost()) {
671     RenderWidgetHostImpl* render_widget_host =
672         RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
673     guest_device_scale_factor_ = params.scale_factor;
674     render_widget_host->NotifyScreenInfoChanged();
675   }
676 
677   if (last_seen_browser_plugin_size_ != params.view_size) {
678     delegate_->ElementSizeChanged(last_seen_browser_plugin_size_,
679                                   params.view_size);
680     last_seen_browser_plugin_size_ = params.view_size;
681   }
682 
683   // Just resize the WebContents and repaint if needed.
684   if (!params.view_size.IsEmpty())
685     GetWebContents()->GetView()->SizeContents(params.view_size);
686   if (params.repaint)
687     Send(new ViewMsg_Repaint(routing_id(), params.view_size));
688 }
689 
OnSetFocus(int browser_plugin_instance_id,bool focused)690 void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
691                                     bool focused) {
692   RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView();
693   RenderWidgetHost* rwh = rwhv ? rwhv->GetRenderWidgetHost() : NULL;
694   SetFocus(rwh, focused);
695 }
696 
OnSetEditCommandsForNextKeyEvent(int browser_plugin_instance_id,const std::vector<EditCommand> & edit_commands)697 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
698     int browser_plugin_instance_id,
699     const std::vector<EditCommand>& edit_commands) {
700   Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
701                                                    edit_commands));
702 }
703 
OnSetVisibility(int browser_plugin_instance_id,bool visible)704 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
705                                          bool visible) {
706   guest_visible_ = visible;
707   if (embedder_visible_ && guest_visible_)
708     GetWebContents()->WasShown();
709   else
710     GetWebContents()->WasHidden();
711 }
712 
OnUnlockMouse()713 void BrowserPluginGuest::OnUnlockMouse() {
714   SendMessageToEmbedder(
715       new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false));
716 }
717 
OnUnlockMouseAck(int browser_plugin_instance_id)718 void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
719   // mouse_locked_ could be false here if the lock attempt was cancelled due
720   // to window focus, or for various other reasons before the guest was informed
721   // of the lock's success.
722   if (mouse_locked_)
723     Send(new ViewMsg_MouseLockLost(routing_id()));
724   mouse_locked_ = false;
725 }
726 
OnCopyFromCompositingSurfaceAck(int browser_plugin_instance_id,int request_id,const SkBitmap & bitmap)727 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
728     int browser_plugin_instance_id,
729     int request_id,
730     const SkBitmap& bitmap) {
731   CHECK(copy_request_callbacks_.count(request_id));
732   if (!copy_request_callbacks_.count(request_id))
733     return;
734   const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
735   callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
736   copy_request_callbacks_.erase(request_id);
737 }
738 
OnUpdateGeometry(int browser_plugin_instance_id,const gfx::Rect & view_rect)739 void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id,
740                                           const gfx::Rect& view_rect) {
741   // The plugin has moved within the embedder without resizing or the
742   // embedder/container's view rect changing.
743   guest_window_rect_ = view_rect;
744   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
745       GetWebContents()->GetRenderViewHost());
746   if (rvh)
747     rvh->SendScreenRects();
748 }
749 
OnHasTouchEventHandlers(bool accept)750 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
751   SendMessageToEmbedder(
752       new BrowserPluginMsg_ShouldAcceptTouchEvents(
753           browser_plugin_instance_id(), accept));
754 }
755 
756 #if defined(OS_MACOSX)
OnShowPopup(RenderFrameHost * render_frame_host,const FrameHostMsg_ShowPopup_Params & params)757 void BrowserPluginGuest::OnShowPopup(
758     RenderFrameHost* render_frame_host,
759     const FrameHostMsg_ShowPopup_Params& params) {
760   gfx::Rect translated_bounds(params.bounds);
761   translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
762   BrowserPluginPopupMenuHelper popup_menu_helper(
763       embedder_web_contents_->GetRenderViewHost(), render_frame_host);
764   popup_menu_helper.ShowPopupMenu(translated_bounds,
765                                   params.item_height,
766                                   params.item_font_size,
767                                   params.selected_item,
768                                   params.popup_items,
769                                   params.right_aligned,
770                                   params.allow_multiple_selection);
771 }
772 #endif
773 
OnShowWidget(int route_id,const gfx::Rect & initial_pos)774 void BrowserPluginGuest::OnShowWidget(int route_id,
775                                       const gfx::Rect& initial_pos) {
776   GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
777 }
778 
OnTakeFocus(bool reverse)779 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
780   SendMessageToEmbedder(
781       new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse));
782 }
783 
OnTextInputTypeChanged(ui::TextInputType type,ui::TextInputMode input_mode,bool can_compose_inline)784 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
785                                                 ui::TextInputMode input_mode,
786                                                 bool can_compose_inline) {
787   // Save the state of text input so we can restore it on focus.
788   last_text_input_type_ = type;
789   last_input_mode_ = input_mode;
790   last_can_compose_inline_ = can_compose_inline;
791 
792   static_cast<RenderWidgetHostViewBase*>(
793       web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
794           type, input_mode, can_compose_inline);
795 }
796 
OnImeCancelComposition()797 void BrowserPluginGuest::OnImeCancelComposition() {
798   static_cast<RenderWidgetHostViewBase*>(
799       web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
800 }
801 
802 #if defined(OS_MACOSX) || defined(USE_AURA)
OnImeCompositionRangeChanged(const gfx::Range & range,const std::vector<gfx::Rect> & character_bounds)803 void BrowserPluginGuest::OnImeCompositionRangeChanged(
804       const gfx::Range& range,
805       const std::vector<gfx::Rect>& character_bounds) {
806   static_cast<RenderWidgetHostViewBase*>(
807       web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
808           range, character_bounds);
809 }
810 #endif
811 
812 }  // namespace content
813