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