• 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/strings/utf_string_conversions.h"
11 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/frame_host/render_frame_host_impl.h"
15 #include "content/browser/frame_host/render_widget_host_view_guest.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_view_base.h"
20 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/browser/web_contents/web_contents_view_guest.h"
22 #include "content/common/browser_plugin/browser_plugin_messages.h"
23 #include "content/common/content_constants_internal.h"
24 #include "content/common/drag_messages.h"
25 #include "content/common/input_messages.h"
26 #include "content/common/view_messages.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_plugin_guest_manager.h"
29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/render_widget_host_view.h"
31 #include "content/public/browser/user_metrics.h"
32 #include "content/public/browser/web_contents_observer.h"
33 #include "content/public/common/drop_data.h"
34 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
35 
36 #if defined(OS_MACOSX)
37 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
38 #endif
39 
40 namespace content {
41 
42 class BrowserPluginGuest::EmbedderWebContentsObserver
43     : public WebContentsObserver {
44  public:
EmbedderWebContentsObserver(BrowserPluginGuest * guest)45   explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
46       : WebContentsObserver(guest->embedder_web_contents()),
47         browser_plugin_guest_(guest) {
48   }
49 
~EmbedderWebContentsObserver()50   virtual ~EmbedderWebContentsObserver() {
51   }
52 
53   // WebContentsObserver implementation.
WasShown()54   virtual void WasShown() OVERRIDE {
55     browser_plugin_guest_->EmbedderVisibilityChanged(true);
56   }
57 
WasHidden()58   virtual void WasHidden() OVERRIDE {
59     browser_plugin_guest_->EmbedderVisibilityChanged(false);
60   }
61 
62  private:
63   BrowserPluginGuest* browser_plugin_guest_;
64 
65   DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
66 };
67 
BrowserPluginGuest(int instance_id,bool has_render_view,WebContentsImpl * web_contents)68 BrowserPluginGuest::BrowserPluginGuest(
69     int instance_id,
70     bool has_render_view,
71     WebContentsImpl* web_contents)
72     : WebContentsObserver(web_contents),
73       embedder_web_contents_(NULL),
74       instance_id_(instance_id),
75       guest_device_scale_factor_(1.0f),
76       focused_(false),
77       mouse_locked_(false),
78       pending_lock_request_(false),
79       guest_visible_(false),
80       guest_opaque_(true),
81       embedder_visible_(true),
82       auto_size_enabled_(false),
83       copy_request_id_(0),
84       has_render_view_(has_render_view),
85       last_seen_auto_size_enabled_(false),
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_(NULL),
91       weak_ptr_factory_(this) {
92   DCHECK(web_contents);
93 }
94 
WillDestroy()95 void BrowserPluginGuest::WillDestroy() {
96   is_in_destruction_ = true;
97   embedder_web_contents_ = NULL;
98   delegate_ = NULL;
99 }
100 
AsWeakPtr()101 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
102   return weak_ptr_factory_.GetWeakPtr();
103 }
104 
LockMouse(bool allowed)105 bool BrowserPluginGuest::LockMouse(bool allowed) {
106   if (!attached() || (mouse_locked_ == allowed))
107     return false;
108 
109   return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
110 }
111 
Destroy()112 void BrowserPluginGuest::Destroy() {
113   if (!delegate_)
114     return;
115   delegate_->Destroy();
116 }
117 
OnMessageReceivedFromEmbedder(const IPC::Message & message)118 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
119     const IPC::Message& message) {
120   bool handled = true;
121   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
122     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
123                         OnCompositorFrameSwappedACK)
124     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
125                         OnCopyFromCompositingSurfaceAck)
126     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
127                         OnDragStatusUpdate)
128     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
129                         OnExecuteEditCommand)
130     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
131                         OnExtendSelectionAndDelete)
132     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
133                         OnHandleInputEvent)
134     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
135                         OnImeConfirmComposition)
136     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
137                         OnImeSetComposition)
138     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
139     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
140     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
141                         OnReclaimCompositorResources)
142     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
143     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetAutoSize)
144     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
145                         OnSetEditCommandsForNextKeyEvent)
146     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
147     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
148                         OnSetContentsOpaque)
149     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
150     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
151     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
152     IPC_MESSAGE_UNHANDLED(handled = false)
153   IPC_END_MESSAGE_MAP()
154   return handled;
155 }
156 
Initialize(const BrowserPluginHostMsg_Attach_Params & params,WebContentsImpl * embedder_web_contents,const base::DictionaryValue & extra_params)157 void BrowserPluginGuest::Initialize(
158     const BrowserPluginHostMsg_Attach_Params& params,
159     WebContentsImpl* embedder_web_contents,
160     const base::DictionaryValue& extra_params) {
161   focused_ = params.focused;
162   guest_visible_ = params.visible;
163   guest_opaque_ = params.opaque;
164   guest_window_rect_ = gfx::Rect(params.origin,
165                                  params.resize_guest_params.view_size);
166 
167   auto_size_enabled_ = params.auto_size_params.enable;
168   max_auto_size_ = params.auto_size_params.max_size;
169   min_auto_size_ = params.auto_size_params.min_size;
170 
171   // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
172   // be attached.
173   embedder_web_contents_ = embedder_web_contents;
174 
175   WebContentsViewGuest* new_view =
176       static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
177   new_view->OnGuestInitialized(embedder_web_contents->GetView());
178 
179   RendererPreferences* renderer_prefs =
180       GetWebContents()->GetMutableRendererPrefs();
181   std::string guest_user_agent_override = renderer_prefs->user_agent_override;
182   // Copy renderer preferences (and nothing else) from the embedder's
183   // WebContents to the guest.
184   //
185   // For GTK and Aura this is necessary to get proper renderer configuration
186   // values for caret blinking interval, colors related to selection and
187   // focus.
188   *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
189   renderer_prefs->user_agent_override = guest_user_agent_override;
190 
191   // We would like the guest to report changes to frame names so that we can
192   // update the BrowserPlugin's corresponding 'name' attribute.
193   // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
194   renderer_prefs->report_frame_name_changes = true;
195   // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
196   // navigations still continue to function inside the app.
197   renderer_prefs->browser_handles_all_top_level_requests = false;
198   // Disable "client blocked" error page for browser plugin.
199   renderer_prefs->disable_client_blocked_error_page = true;
200 
201   embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
202 
203   OnSetAutoSize(
204       instance_id_, params.auto_size_params, params.resize_guest_params);
205 
206   // Create a swapped out RenderView for the guest in the embedder render
207   // process, so that the embedder can access the guest's window object.
208   int guest_routing_id =
209       GetWebContents()->CreateSwappedOutRenderView(
210           embedder_web_contents_->GetSiteInstance());
211   SendMessageToEmbedder(
212       new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
213                                                    guest_routing_id));
214 
215   WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
216   prefs.navigate_on_drag_drop = false;
217   GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
218 
219   // Enable input method for guest if it's enabled for the embedder.
220   if (static_cast<RenderViewHostImpl*>(
221       embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
222     RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
223         GetWebContents()->GetRenderViewHost());
224     guest_rvh->SetInputMethodActive(true);
225   }
226 
227   // Inform the embedder of the guest's attachment.
228   SendMessageToEmbedder(new BrowserPluginMsg_Attach_ACK(instance_id_));
229 }
230 
~BrowserPluginGuest()231 BrowserPluginGuest::~BrowserPluginGuest() {
232 }
233 
234 // static
Create(int instance_id,SiteInstance * guest_site_instance,WebContentsImpl * web_contents,scoped_ptr<base::DictionaryValue> extra_params,BrowserPluginGuest * opener)235 BrowserPluginGuest* BrowserPluginGuest::Create(
236     int instance_id,
237     SiteInstance* guest_site_instance,
238     WebContentsImpl* web_contents,
239     scoped_ptr<base::DictionaryValue> extra_params,
240     BrowserPluginGuest* opener) {
241   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
242   BrowserPluginGuest* guest = new BrowserPluginGuest(
243       instance_id, web_contents->opener() != NULL, web_contents);
244   web_contents->SetBrowserPluginGuest(guest);
245   WebContents* opener_web_contents = NULL;
246   if (opener) {
247     opener_web_contents = opener->GetWebContents();
248     guest_site_instance = opener_web_contents->GetSiteInstance();
249   }
250   BrowserPluginGuestDelegate* delegate = NULL;
251   GetContentClient()->browser()->GuestWebContentsCreated(
252       instance_id,
253       guest_site_instance,
254       web_contents,
255       opener_web_contents,
256       &delegate,
257       extra_params.Pass());
258   if (delegate) {
259     delegate->RegisterDestructionCallback(
260         base::Bind(&BrowserPluginGuest::WillDestroy,
261                    base::Unretained(guest)));
262     guest->set_delegate(delegate);
263   }
264   return guest;
265 }
266 
267 // static
IsGuest(WebContentsImpl * web_contents)268 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
269   return web_contents && web_contents->GetBrowserPluginGuest();
270 }
271 
272 // static
IsGuest(RenderViewHostImpl * render_view_host)273 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
274   return render_view_host && IsGuest(
275       static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
276           render_view_host)));
277 }
278 
GetEmbedderRenderWidgetHostView()279 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
280   if (!attached())
281     return NULL;
282   return embedder_web_contents_->GetRenderWidgetHostView();
283 }
284 
UpdateVisibility()285 void BrowserPluginGuest::UpdateVisibility() {
286   OnSetVisibility(instance_id_, visible());
287 }
288 
CopyFromCompositingSurface(gfx::Rect src_subrect,gfx::Size dst_size,const base::Callback<void (bool,const SkBitmap &)> & callback)289 void BrowserPluginGuest::CopyFromCompositingSurface(
290       gfx::Rect src_subrect,
291       gfx::Size dst_size,
292       const base::Callback<void(bool, const SkBitmap&)>& callback) {
293   copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
294   SendMessageToEmbedder(
295       new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
296           copy_request_id_, src_subrect, dst_size));
297 }
298 
299 BrowserPluginGuestManager*
GetBrowserPluginGuestManager() const300 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
301   return GetWebContents()->GetBrowserContext()->GetGuestManager();
302 }
303 
304 // screen.
ToGuestRect(const gfx::Rect & bounds)305 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
306   gfx::Rect guest_rect(bounds);
307   guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
308   return guest_rect;
309 }
310 
EmbedderVisibilityChanged(bool visible)311 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
312   embedder_visible_ = visible;
313   UpdateVisibility();
314 }
315 
PointerLockPermissionResponse(bool allow)316 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
317   SendMessageToEmbedder(
318       new BrowserPluginMsg_SetMouseLock(instance_id(), allow));
319 }
320 
GetWebContents() const321 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
322   return static_cast<WebContentsImpl*>(web_contents());
323 }
324 
GetScreenCoordinates(const gfx::Point & relative_position) const325 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
326     const gfx::Point& relative_position) const {
327   gfx::Point screen_pos(relative_position);
328   screen_pos += guest_window_rect_.OffsetFromOrigin();
329   return screen_pos;
330 }
331 
InAutoSizeBounds(const gfx::Size & size) const332 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
333   return size.width() <= max_auto_size_.width() &&
334       size.height() <= max_auto_size_.height();
335 }
336 
SendMessageToEmbedder(IPC::Message * msg)337 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
338   if (!attached()) {
339     // Some pages such as data URLs, javascript URLs, and about:blank
340     // do not load external resources and so they load prior to attachment.
341     // As a result, we must save all these IPCs until attachment and then
342     // forward them so that the embedder gets a chance to see and process
343     // the load events.
344     pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
345     return;
346   }
347   msg->set_routing_id(embedder_web_contents_->GetRoutingID());
348   embedder_web_contents_->Send(msg);
349 }
350 
DragSourceEndedAt(int client_x,int client_y,int screen_x,int screen_y,blink::WebDragOperation operation)351 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
352     int screen_x, int screen_y, blink::WebDragOperation operation) {
353   web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
354       screen_x, screen_y, operation);
355 }
356 
EndSystemDrag()357 void BrowserPluginGuest::EndSystemDrag() {
358   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
359       GetWebContents()->GetRenderViewHost());
360   guest_rvh->DragSourceSystemDragEnded();
361 }
362 
SendQueuedMessages()363 void BrowserPluginGuest::SendQueuedMessages() {
364   if (!attached())
365     return;
366 
367   while (!pending_messages_.empty()) {
368     linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
369     pending_messages_.pop_front();
370     SendMessageToEmbedder(message_ptr.release());
371   }
372 }
373 
DidCommitProvisionalLoadForFrame(int64 frame_id,const base::string16 & frame_unique_name,bool is_main_frame,const GURL & url,PageTransition transition_type,RenderViewHost * render_view_host)374 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
375     int64 frame_id,
376     const base::string16& frame_unique_name,
377     bool is_main_frame,
378     const GURL& url,
379     PageTransition transition_type,
380     RenderViewHost* render_view_host) {
381   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
382 }
383 
RenderViewReady()384 void BrowserPluginGuest::RenderViewReady() {
385   RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
386   // TODO(fsamuel): Investigate whether it's possible to update state earlier
387   // here (see http://crbug.com/158151).
388   Send(new InputMsg_SetFocus(routing_id(), focused_));
389   UpdateVisibility();
390   if (auto_size_enabled_)
391     rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
392   else
393     rvh->DisableAutoResize(full_size_);
394 
395   OnSetContentsOpaque(instance_id_, guest_opaque_);
396 
397   RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
398       base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
399 }
400 
RenderProcessGone(base::TerminationStatus status)401 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
402   SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
403   switch (status) {
404     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
405       RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
406       break;
407     case base::TERMINATION_STATUS_PROCESS_CRASHED:
408       RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
409       break;
410     case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
411       RecordAction(
412           base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
413       break;
414     default:
415       break;
416   }
417 }
418 
419 // static
ShouldForwardToBrowserPluginGuest(const IPC::Message & message)420 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
421     const IPC::Message& message) {
422   switch (message.type()) {
423     case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
424     case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
425     case BrowserPluginHostMsg_DragStatusUpdate::ID:
426     case BrowserPluginHostMsg_ExecuteEditCommand::ID:
427     case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
428     case BrowserPluginHostMsg_HandleInputEvent::ID:
429     case BrowserPluginHostMsg_ImeConfirmComposition::ID:
430     case BrowserPluginHostMsg_ImeSetComposition::ID:
431     case BrowserPluginHostMsg_LockMouse_ACK::ID:
432     case BrowserPluginHostMsg_PluginDestroyed::ID:
433     case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
434     case BrowserPluginHostMsg_ResizeGuest::ID:
435     case BrowserPluginHostMsg_SetAutoSize::ID:
436     case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
437     case BrowserPluginHostMsg_SetFocus::ID:
438     case BrowserPluginHostMsg_SetContentsOpaque::ID:
439     case BrowserPluginHostMsg_SetVisibility::ID:
440     case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
441     case BrowserPluginHostMsg_UpdateGeometry::ID:
442       return true;
443     default:
444       return false;
445   }
446 }
447 
OnMessageReceived(const IPC::Message & message)448 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
449   bool handled = true;
450   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
451     IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
452                         OnHasTouchEventHandlers)
453     IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
454     IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
455  #if defined(OS_MACOSX)
456     // MacOSX creates and populates platform-specific select drop-down menus
457     // whereas other platforms merely create a popup window that the guest
458     // renderer process paints inside.
459     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
460  #endif
461     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
462     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
463     IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
464                         OnTextInputStateChanged)
465     IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
466                         OnImeCancelComposition)
467 #if defined(OS_MACOSX) || defined(USE_AURA)
468     IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
469                         OnImeCompositionRangeChanged)
470 #endif
471     IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
472     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
473     IPC_MESSAGE_UNHANDLED(handled = false)
474   IPC_END_MESSAGE_MAP()
475   return handled;
476 }
477 
Attach(WebContentsImpl * embedder_web_contents,const BrowserPluginHostMsg_Attach_Params & params,const base::DictionaryValue & extra_params)478 void BrowserPluginGuest::Attach(
479     WebContentsImpl* embedder_web_contents,
480     const BrowserPluginHostMsg_Attach_Params& params,
481     const base::DictionaryValue& extra_params) {
482   if (attached())
483     return;
484 
485   if (delegate_)
486     delegate_->WillAttach(embedder_web_contents, extra_params);
487 
488   // If a RenderView has already been created for this new window, then we need
489   // to initialize the browser-side state now so that the RenderFrameHostManager
490   // does not create a new RenderView on navigation.
491   if (has_render_view_) {
492     static_cast<RenderViewHostImpl*>(
493         GetWebContents()->GetRenderViewHost())->Init();
494     WebContentsViewGuest* new_view =
495         static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
496     new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
497   }
498 
499   Initialize(params, embedder_web_contents, extra_params);
500 
501   SendQueuedMessages();
502 
503   if (delegate_)
504     delegate_->DidAttach();
505 
506   RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
507 }
508 
OnCompositorFrameSwappedACK(int instance_id,const FrameHostMsg_CompositorFrameSwappedACK_Params & params)509 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
510     int instance_id,
511     const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
512   RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
513                                                    params.output_surface_id,
514                                                    params.producing_host_id,
515                                                    params.ack);
516 }
517 
OnDragStatusUpdate(int instance_id,blink::WebDragStatus drag_status,const DropData & drop_data,blink::WebDragOperationsMask mask,const gfx::Point & location)518 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
519                                             blink::WebDragStatus drag_status,
520                                             const DropData& drop_data,
521                                             blink::WebDragOperationsMask mask,
522                                             const gfx::Point& location) {
523   RenderViewHost* host = GetWebContents()->GetRenderViewHost();
524   switch (drag_status) {
525     case blink::WebDragStatusEnter:
526       embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
527           this);
528       host->DragTargetDragEnter(drop_data, location, location, mask, 0);
529       break;
530     case blink::WebDragStatusOver:
531       host->DragTargetDragOver(location, location, mask, 0);
532       break;
533     case blink::WebDragStatusLeave:
534       embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
535       host->DragTargetDragLeave();
536       break;
537     case blink::WebDragStatusDrop:
538       host->DragTargetDrop(location, location, 0);
539       EndSystemDrag();
540       break;
541     case blink::WebDragStatusUnknown:
542       NOTREACHED();
543   }
544 }
545 
OnExecuteEditCommand(int instance_id,const std::string & name)546 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
547                                               const std::string& name) {
548   Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
549 }
550 
OnImeSetComposition(int instance_id,const std::string & text,const std::vector<blink::WebCompositionUnderline> & underlines,int selection_start,int selection_end)551 void BrowserPluginGuest::OnImeSetComposition(
552     int instance_id,
553     const std::string& text,
554     const std::vector<blink::WebCompositionUnderline>& underlines,
555     int selection_start,
556     int selection_end) {
557   Send(new ViewMsg_ImeSetComposition(routing_id(),
558                                      base::UTF8ToUTF16(text), underlines,
559                                      selection_start, selection_end));
560 }
561 
OnImeConfirmComposition(int instance_id,const std::string & text,bool keep_selection)562 void BrowserPluginGuest::OnImeConfirmComposition(
563     int instance_id,
564     const std::string& text,
565     bool keep_selection) {
566   Send(new ViewMsg_ImeConfirmComposition(routing_id(),
567                                          base::UTF8ToUTF16(text),
568                                          gfx::Range::InvalidRange(),
569                                          keep_selection));
570 }
571 
OnExtendSelectionAndDelete(int instance_id,int before,int after)572 void BrowserPluginGuest::OnExtendSelectionAndDelete(
573     int instance_id,
574     int before,
575     int after) {
576   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
577       web_contents()->GetFocusedFrame());
578   if (rfh)
579     rfh->ExtendSelectionAndDelete(before, after);
580 }
581 
OnReclaimCompositorResources(int instance_id,const FrameHostMsg_ReclaimCompositorResources_Params & params)582 void BrowserPluginGuest::OnReclaimCompositorResources(
583     int instance_id,
584     const FrameHostMsg_ReclaimCompositorResources_Params& params) {
585   RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
586                                                        params.output_surface_id,
587                                                        params.renderer_host_id,
588                                                        params.ack);
589 }
590 
OnHandleInputEvent(int instance_id,const gfx::Rect & guest_window_rect,const blink::WebInputEvent * event)591 void BrowserPluginGuest::OnHandleInputEvent(
592     int instance_id,
593     const gfx::Rect& guest_window_rect,
594     const blink::WebInputEvent* event) {
595   guest_window_rect_ = guest_window_rect;
596   // If the embedder's RWHV is destroyed then that means that the embedder's
597   // window has been closed but the embedder's WebContents has not yet been
598   // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
599   // if there is a visible embedder.
600   if (embedder_web_contents_->GetRenderWidgetHostView()) {
601     guest_screen_rect_ = guest_window_rect;
602     guest_screen_rect_.Offset(
603         embedder_web_contents_->GetRenderWidgetHostView()->
604             GetViewBounds().OffsetFromOrigin());
605   }
606   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
607       GetWebContents()->GetRenderViewHost());
608 
609   if (blink::WebInputEvent::isMouseEventType(event->type)) {
610     guest_rvh->ForwardMouseEvent(
611         *static_cast<const blink::WebMouseEvent*>(event));
612     return;
613   }
614 
615   if (event->type == blink::WebInputEvent::MouseWheel) {
616     guest_rvh->ForwardWheelEvent(
617         *static_cast<const blink::WebMouseWheelEvent*>(event));
618     return;
619   }
620 
621   if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
622     RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
623         embedder_web_contents_->GetRenderViewHost());
624     if (!embedder_rvh->GetLastKeyboardEvent())
625       return;
626     NativeWebKeyboardEvent keyboard_event(
627         *embedder_rvh->GetLastKeyboardEvent());
628     guest_rvh->ForwardKeyboardEvent(keyboard_event);
629     return;
630   }
631 
632   if (blink::WebInputEvent::isTouchEventType(event->type)) {
633     guest_rvh->ForwardTouchEventWithLatencyInfo(
634         *static_cast<const blink::WebTouchEvent*>(event),
635         ui::LatencyInfo());
636     return;
637   }
638 
639   if (blink::WebInputEvent::isGestureEventType(event->type)) {
640     guest_rvh->ForwardGestureEvent(
641         *static_cast<const blink::WebGestureEvent*>(event));
642     return;
643   }
644 }
645 
OnLockMouse(bool user_gesture,bool last_unlocked_by_target,bool privileged)646 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
647                                      bool last_unlocked_by_target,
648                                      bool privileged) {
649   if (pending_lock_request_) {
650     // Immediately reject the lock because only one pointerLock may be active
651     // at a time.
652     Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
653     return;
654   }
655 
656   if (!delegate_)
657     return;
658 
659   pending_lock_request_ = true;
660 
661   delegate_->RequestPointerLockPermission(
662       user_gesture,
663       last_unlocked_by_target,
664       base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
665                  weak_ptr_factory_.GetWeakPtr()));
666 }
667 
OnLockMouseAck(int instance_id,bool succeeded)668 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
669   Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
670   pending_lock_request_ = false;
671   if (succeeded)
672     mouse_locked_ = true;
673 }
674 
OnPluginDestroyed(int instance_id)675 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
676   Destroy();
677 }
678 
OnResizeGuest(int instance_id,const BrowserPluginHostMsg_ResizeGuest_Params & params)679 void BrowserPluginGuest::OnResizeGuest(
680     int instance_id,
681     const BrowserPluginHostMsg_ResizeGuest_Params& params) {
682   if (!params.size_changed)
683     return;
684   // BrowserPlugin manages resize flow control itself and does not depend
685   // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
686   // here. If we are setting the size for the first time before navigating then
687   // BrowserPluginGuest does not yet have a RenderViewHost.
688   if (GetWebContents()->GetRenderViewHost()) {
689     RenderWidgetHostImpl* render_widget_host =
690         RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
691     render_widget_host->ResetSizeAndRepaintPendingFlags();
692 
693     if (guest_device_scale_factor_ != params.scale_factor) {
694       guest_device_scale_factor_ = params.scale_factor;
695       render_widget_host->NotifyScreenInfoChanged();
696     }
697   }
698   // When autosize is turned off and as a result there is a layout change, we
699   // send a sizechanged event.
700   if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
701       !params.view_size.IsEmpty() && delegate_) {
702     delegate_->SizeChanged(last_seen_view_size_, params.view_size);
703     last_seen_auto_size_enabled_ = false;
704   }
705   // Just resize the WebContents and repaint if needed.
706   full_size_ = params.view_size;
707   if (!params.view_size.IsEmpty())
708     GetWebContents()->GetView()->SizeContents(params.view_size);
709   if (params.repaint)
710     Send(new ViewMsg_Repaint(routing_id(), params.view_size));
711 }
712 
OnSetFocus(int instance_id,bool focused)713 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
714   focused_ = focused;
715   Send(new InputMsg_SetFocus(routing_id(), focused));
716   if (!focused && mouse_locked_)
717     OnUnlockMouse();
718 
719   // Restore the last seen state of text input to the view.
720   RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
721       web_contents()->GetRenderWidgetHostView());
722   if (rwhv) {
723     ViewHostMsg_TextInputState_Params params;
724     params.type = last_text_input_type_;
725     params.mode = last_input_mode_;
726     params.can_compose_inline = last_can_compose_inline_;
727     rwhv->TextInputStateChanged(params);
728   }
729 }
730 
OnSetAutoSize(int instance_id,const BrowserPluginHostMsg_AutoSize_Params & auto_size_params,const BrowserPluginHostMsg_ResizeGuest_Params & resize_guest_params)731 void BrowserPluginGuest::OnSetAutoSize(
732     int instance_id,
733     const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
734     const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
735   bool old_auto_size_enabled = auto_size_enabled_;
736   gfx::Size old_max_size = max_auto_size_;
737   gfx::Size old_min_size = min_auto_size_;
738   auto_size_enabled_ = auto_size_params.enable;
739   max_auto_size_ = auto_size_params.max_size;
740   min_auto_size_ = auto_size_params.min_size;
741   if (auto_size_enabled_ && (!old_auto_size_enabled ||
742                              (old_max_size != max_auto_size_) ||
743                              (old_min_size != min_auto_size_))) {
744     RecordAction(
745         base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
746     GetWebContents()->GetRenderViewHost()->EnableAutoResize(
747         min_auto_size_, max_auto_size_);
748     // TODO(fsamuel): If we're changing autosize parameters, then we force
749     // the guest to completely repaint itself.
750     // Ideally, we shouldn't need to do this unless |max_auto_size_| has
751     // changed.
752     // However, even in that case, layout may not change and so we may
753     // not get a full frame worth of pixels.
754     Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
755   } else if (!auto_size_enabled_ && old_auto_size_enabled) {
756     GetWebContents()->GetRenderViewHost()->DisableAutoResize(
757         resize_guest_params.view_size);
758   }
759   OnResizeGuest(instance_id_, resize_guest_params);
760 }
761 
OnSetEditCommandsForNextKeyEvent(int instance_id,const std::vector<EditCommand> & edit_commands)762 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
763     int instance_id,
764     const std::vector<EditCommand>& edit_commands) {
765   Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
766                                                    edit_commands));
767 }
768 
OnSetContentsOpaque(int instance_id,bool opaque)769 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
770   guest_opaque_ = opaque;
771   Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
772 }
773 
OnSetVisibility(int instance_id,bool visible)774 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
775   guest_visible_ = visible;
776   if (embedder_visible_ && guest_visible_)
777     GetWebContents()->WasShown();
778   else
779     GetWebContents()->WasHidden();
780 }
781 
OnUnlockMouse()782 void BrowserPluginGuest::OnUnlockMouse() {
783   SendMessageToEmbedder(
784       new BrowserPluginMsg_SetMouseLock(instance_id(), false));
785 }
786 
OnUnlockMouseAck(int instance_id)787 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
788   // mouse_locked_ could be false here if the lock attempt was cancelled due
789   // to window focus, or for various other reasons before the guest was informed
790   // of the lock's success.
791   if (mouse_locked_)
792     Send(new ViewMsg_MouseLockLost(routing_id()));
793   mouse_locked_ = false;
794 }
795 
OnCopyFromCompositingSurfaceAck(int instance_id,int request_id,const SkBitmap & bitmap)796 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
797     int instance_id,
798     int request_id,
799     const SkBitmap& bitmap) {
800   CHECK(copy_request_callbacks_.count(request_id));
801   if (!copy_request_callbacks_.count(request_id))
802     return;
803   const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
804   callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
805   copy_request_callbacks_.erase(request_id);
806 }
807 
OnUpdateGeometry(int instance_id,const gfx::Rect & view_rect)808 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
809                                           const gfx::Rect& view_rect) {
810   // The plugin has moved within the embedder without resizing or the
811   // embedder/container's view rect changing.
812   guest_window_rect_ = view_rect;
813   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
814       GetWebContents()->GetRenderViewHost());
815   if (rvh)
816     rvh->SendScreenRects();
817 }
818 
OnHasTouchEventHandlers(bool accept)819 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
820   SendMessageToEmbedder(
821       new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
822 }
823 
OnSetCursor(const WebCursor & cursor)824 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
825   SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
826 }
827 
828 #if defined(OS_MACOSX)
OnShowPopup(const ViewHostMsg_ShowPopup_Params & params)829 void BrowserPluginGuest::OnShowPopup(
830     const ViewHostMsg_ShowPopup_Params& params) {
831   gfx::Rect translated_bounds(params.bounds);
832   translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
833   BrowserPluginPopupMenuHelper popup_menu_helper(
834       embedder_web_contents_->GetRenderViewHost(),
835       GetWebContents()->GetRenderViewHost());
836   popup_menu_helper.ShowPopupMenu(translated_bounds,
837                                   params.item_height,
838                                   params.item_font_size,
839                                   params.selected_item,
840                                   params.popup_items,
841                                   params.right_aligned,
842                                   params.allow_multiple_selection);
843 }
844 #endif
845 
OnShowWidget(int route_id,const gfx::Rect & initial_pos)846 void BrowserPluginGuest::OnShowWidget(int route_id,
847                                       const gfx::Rect& initial_pos) {
848   GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
849 }
850 
OnTakeFocus(bool reverse)851 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
852   SendMessageToEmbedder(
853       new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
854 }
855 
OnUpdateRect(const ViewHostMsg_UpdateRect_Params & params)856 void BrowserPluginGuest::OnUpdateRect(
857     const ViewHostMsg_UpdateRect_Params& params) {
858   BrowserPluginMsg_UpdateRect_Params relay_params;
859   relay_params.view_size = params.view_size;
860   relay_params.scale_factor = params.scale_factor;
861   relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
862       params.flags);
863 
864   bool size_changed = last_seen_view_size_ != params.view_size;
865   gfx::Size old_size = last_seen_view_size_;
866   last_seen_view_size_ = params.view_size;
867 
868   if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
869       size_changed && delegate_) {
870     delegate_->SizeChanged(old_size, last_seen_view_size_);
871   }
872   last_seen_auto_size_enabled_ = auto_size_enabled_;
873 
874   SendMessageToEmbedder(
875       new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
876 }
877 
OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params & params)878 void BrowserPluginGuest::OnTextInputStateChanged(
879     const ViewHostMsg_TextInputState_Params& params) {
880   // Save the state of text input so we can restore it on focus.
881   last_text_input_type_ = params.type;
882   last_input_mode_ = params.mode;
883   last_can_compose_inline_ = params.can_compose_inline;
884 
885   static_cast<RenderWidgetHostViewBase*>(
886       web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params);
887 }
888 
OnImeCancelComposition()889 void BrowserPluginGuest::OnImeCancelComposition() {
890   static_cast<RenderWidgetHostViewBase*>(
891       web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
892 }
893 
894 #if defined(OS_MACOSX) || defined(USE_AURA)
OnImeCompositionRangeChanged(const gfx::Range & range,const std::vector<gfx::Rect> & character_bounds)895 void BrowserPluginGuest::OnImeCompositionRangeChanged(
896       const gfx::Range& range,
897       const std::vector<gfx::Rect>& character_bounds) {
898   static_cast<RenderWidgetHostViewBase*>(
899       web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
900           range, character_bounds);
901 }
902 #endif
903 
904 }  // namespace content
905