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