Home | History | Annotate | Download | only in browser_plugin
      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     : 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 
     95 void BrowserPluginGuest::WillDestroy() {
     96   is_in_destruction_ = true;
     97   embedder_web_contents_ = NULL;
     98   delegate_ = NULL;
     99 }
    100 
    101 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
    102   return weak_ptr_factory_.GetWeakPtr();
    103 }
    104 
    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 
    112 void BrowserPluginGuest::Destroy() {
    113   if (!delegate_)
    114     return;
    115   delegate_->Destroy();
    116 }
    117 
    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 
    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 
    231 BrowserPluginGuest::~BrowserPluginGuest() {
    232 }
    233 
    234 // static
    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
    268 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
    269   return web_contents && web_contents->GetBrowserPluginGuest();
    270 }
    271 
    272 // static
    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 
    279 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
    280   if (!attached())
    281     return NULL;
    282   return embedder_web_contents_->GetRenderWidgetHostView();
    283 }
    284 
    285 void BrowserPluginGuest::UpdateVisibility() {
    286   OnSetVisibility(instance_id_, visible());
    287 }
    288 
    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*
    300 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
    301   return GetWebContents()->GetBrowserContext()->GetGuestManager();
    302 }
    303 
    304 // screen.
    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 
    311 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
    312   embedder_visible_ = visible;
    313   UpdateVisibility();
    314 }
    315 
    316 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
    317   SendMessageToEmbedder(
    318       new BrowserPluginMsg_SetMouseLock(instance_id(), allow));
    319 }
    320 
    321 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
    322   return static_cast<WebContentsImpl*>(web_contents());
    323 }
    324 
    325 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 
    332 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 
    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 
    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 
    357 void BrowserPluginGuest::EndSystemDrag() {
    358   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
    359       GetWebContents()->GetRenderViewHost());
    360   guest_rvh->DragSourceSystemDragEnded();
    361 }
    362 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    546 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
    547                                               const std::string& name) {
    548   Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
    549 }
    550 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    675 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
    676   Destroy();
    677 }
    678 
    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 
    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 
    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 
    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 
    769 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
    770   guest_opaque_ = opaque;
    771   Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
    772 }
    773 
    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 
    782 void BrowserPluginGuest::OnUnlockMouse() {
    783   SendMessageToEmbedder(
    784       new BrowserPluginMsg_SetMouseLock(instance_id(), false));
    785 }
    786 
    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 
    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 
    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 
    819 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
    820   SendMessageToEmbedder(
    821       new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
    822 }
    823 
    824 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
    825   SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
    826 }
    827 
    828 #if defined(OS_MACOSX)
    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 
    846 void BrowserPluginGuest::OnShowWidget(int route_id,
    847                                       const gfx::Rect& initial_pos) {
    848   GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
    849 }
    850 
    851 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
    852   SendMessageToEmbedder(
    853       new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
    854 }
    855 
    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 
    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 
    889 void BrowserPluginGuest::OnImeCancelComposition() {
    890   static_cast<RenderWidgetHostViewBase*>(
    891       web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
    892 }
    893 
    894 #if defined(OS_MACOSX) || defined(USE_AURA)
    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