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/string_util.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
     13 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
     14 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
     15 #include "content/browser/browser_thread_impl.h"
     16 #include "content/browser/child_process_security_policy_impl.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/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_constants.h"
     23 #include "content/common/browser_plugin/browser_plugin_messages.h"
     24 #include "content/common/content_constants_internal.h"
     25 #include "content/common/drag_messages.h"
     26 #include "content/common/gpu/gpu_messages.h"
     27 #include "content/common/input_messages.h"
     28 #include "content/common/view_messages.h"
     29 #include "content/port/browser/render_view_host_delegate_view.h"
     30 #include "content/port/browser/render_widget_host_view_port.h"
     31 #include "content/public/browser/browser_context.h"
     32 #include "content/public/browser/content_browser_client.h"
     33 #include "content/public/browser/geolocation_permission_context.h"
     34 #include "content/public/browser/navigation_controller.h"
     35 #include "content/public/browser/render_process_host.h"
     36 #include "content/public/browser/render_widget_host_view.h"
     37 #include "content/public/browser/resource_request_details.h"
     38 #include "content/public/browser/user_metrics.h"
     39 #include "content/public/browser/web_contents_observer.h"
     40 #include "content/public/browser/web_contents_view.h"
     41 #include "content/public/common/drop_data.h"
     42 #include "content/public/common/media_stream_request.h"
     43 #include "content/public/common/result_codes.h"
     44 #include "content/public/common/url_constants.h"
     45 #include "content/public/common/url_utils.h"
     46 #include "net/url_request/url_request.h"
     47 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
     48 #include "ui/events/keycodes/keyboard_codes.h"
     49 #include "ui/surface/transport_dib.h"
     50 #include "webkit/common/resource_type.h"
     51 
     52 #if defined(OS_MACOSX)
     53 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
     54 #endif
     55 
     56 namespace content {
     57 
     58 // static
     59 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
     60 
     61 // Parent class for the various types of permission requests, each of which
     62 // should be able to handle the response to their permission request.
     63 class BrowserPluginGuest::PermissionRequest :
     64     public base::RefCounted<BrowserPluginGuest::PermissionRequest> {
     65  public:
     66   virtual void Respond(bool should_allow, const std::string& user_input) = 0;
     67   virtual bool AllowedByDefault() const {
     68     return false;
     69   }
     70  protected:
     71   PermissionRequest() {
     72     RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
     73   }
     74   virtual ~PermissionRequest() {}
     75   // Friend RefCounted so that the dtor can be non-public.
     76   friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>;
     77 };
     78 
     79 class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
     80  public:
     81   explicit DownloadRequest(base::Callback<void(bool)> callback)
     82       : callback_(callback) {
     83     RecordAction(
     84         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Download"));
     85   }
     86   virtual void Respond(bool should_allow,
     87                        const std::string& user_input) OVERRIDE {
     88     callback_.Run(should_allow);
     89   }
     90 
     91  private:
     92   virtual ~DownloadRequest() {}
     93   base::Callback<void(bool)> callback_;
     94 };
     95 
     96 class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
     97  public:
     98   GeolocationRequest(GeolocationCallback callback,
     99                      int bridge_id,
    100                      base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory)
    101                      : callback_(callback),
    102                        bridge_id_(bridge_id),
    103                        weak_ptr_factory_(weak_ptr_factory) {
    104     RecordAction(
    105         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Geolocation"));
    106   }
    107 
    108   virtual void Respond(bool should_allow,
    109                        const std::string& user_input) OVERRIDE {
    110     base::WeakPtr<BrowserPluginGuest> guest(weak_ptr_factory_->GetWeakPtr());
    111 
    112     WebContents* web_contents = guest->embedder_web_contents();
    113     if (should_allow && web_contents) {
    114       // If renderer side embedder decides to allow gelocation, we need to check
    115       // if the app/embedder itself has geolocation access.
    116       BrowserContext* browser_context = web_contents->GetBrowserContext();
    117       if (browser_context) {
    118         GeolocationPermissionContext* geolocation_context =
    119             browser_context->GetGeolocationPermissionContext();
    120         if (geolocation_context) {
    121           base::Callback<void(bool)> geolocation_callback = base::Bind(
    122               &BrowserPluginGuest::SetGeolocationPermission,
    123               guest,
    124               callback_,
    125               bridge_id_);
    126           geolocation_context->RequestGeolocationPermission(
    127               web_contents->GetRenderProcessHost()->GetID(),
    128               web_contents->GetRoutingID(),
    129               // The geolocation permission request here is not initiated
    130               // through WebGeolocationPermissionRequest. We are only interested
    131               // in the fact whether the embedder/app has geolocation
    132               // permission. Therefore we use an invalid |bridge_id|.
    133               -1 /* bridge_id */,
    134               web_contents->GetLastCommittedURL(),
    135               geolocation_callback);
    136           return;
    137         }
    138       }
    139     }
    140     guest->SetGeolocationPermission(callback_, bridge_id_, false);
    141   }
    142 
    143  private:
    144   virtual ~GeolocationRequest() {}
    145   base::Callback<void(bool)> callback_;
    146   int bridge_id_;
    147   base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
    148 };
    149 
    150 class BrowserPluginGuest::MediaRequest : public PermissionRequest {
    151  public:
    152   MediaRequest(const MediaStreamRequest& request,
    153                const MediaResponseCallback& callback,
    154                BrowserPluginGuest* guest)
    155                : request_(request),
    156                  callback_(callback),
    157                  guest_(guest) {
    158     RecordAction(
    159         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Media"));
    160   }
    161 
    162   virtual void Respond(bool should_allow,
    163                        const std::string& user_input) OVERRIDE {
    164     WebContentsImpl* web_contents = guest_->embedder_web_contents();
    165     if (should_allow && web_contents) {
    166       // Re-route the request to the embedder's WebContents; the guest gets the
    167       // permission this way.
    168       web_contents->RequestMediaAccessPermission(request_, callback_);
    169     } else {
    170       // Deny the request.
    171       callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
    172     }
    173   }
    174 
    175  private:
    176   virtual ~MediaRequest() {}
    177   MediaStreamRequest request_;
    178   MediaResponseCallback callback_;
    179   BrowserPluginGuest* guest_;
    180 };
    181 
    182 class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
    183  public:
    184   NewWindowRequest(int instance_id, BrowserPluginGuest* guest)
    185       : instance_id_(instance_id),
    186         guest_(guest) {
    187     RecordAction(
    188         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow"));
    189   }
    190 
    191   virtual void Respond(bool should_allow,
    192                        const std::string& user_input) OVERRIDE {
    193     int embedder_render_process_id =
    194         guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
    195     BrowserPluginGuest* guest =
    196         guest_->GetWebContents()->GetBrowserPluginGuestManager()->
    197             GetGuestByInstanceID(instance_id_, embedder_render_process_id);
    198     if (!guest) {
    199       VLOG(0) << "Guest not found. Instance ID: " << instance_id_;
    200       return;
    201     }
    202 
    203     // If we do not destroy the guest then we allow the new window.
    204     if (!should_allow)
    205       guest->Destroy();
    206   }
    207 
    208  private:
    209   virtual ~NewWindowRequest() {}
    210   int instance_id_;
    211   BrowserPluginGuest* guest_;
    212 };
    213 
    214 class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest {
    215  public:
    216   JavaScriptDialogRequest(const DialogClosedCallback& callback)
    217       : callback_(callback) {
    218     RecordAction(
    219         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog"));
    220   }
    221 
    222   virtual void Respond(bool should_allow,
    223                        const std::string& user_input) OVERRIDE {
    224     callback_.Run(should_allow, UTF8ToUTF16(user_input));
    225   }
    226 
    227  private:
    228   virtual ~JavaScriptDialogRequest() {}
    229   DialogClosedCallback callback_;
    230 };
    231 
    232 class BrowserPluginGuest::PointerLockRequest : public PermissionRequest {
    233  public:
    234   PointerLockRequest(BrowserPluginGuest* guest)
    235       : guest_(guest) {
    236     RecordAction(
    237         UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.PointerLock"));
    238   }
    239 
    240   virtual void Respond(bool should_allow,
    241                        const std::string& user_input) OVERRIDE {
    242     guest_->SendMessageToEmbedder(
    243         new BrowserPluginMsg_SetMouseLock(guest_->instance_id(), should_allow));
    244   }
    245 
    246  private:
    247   virtual ~PointerLockRequest() {}
    248   BrowserPluginGuest* guest_;
    249 };
    250 
    251 namespace {
    252 std::string WindowOpenDispositionToString(
    253   WindowOpenDisposition window_open_disposition) {
    254   switch (window_open_disposition) {
    255     case IGNORE_ACTION:
    256       return "ignore";
    257     case SAVE_TO_DISK:
    258       return "save_to_disk";
    259     case CURRENT_TAB:
    260       return "current_tab";
    261     case NEW_BACKGROUND_TAB:
    262       return "new_background_tab";
    263     case NEW_FOREGROUND_TAB:
    264       return "new_foreground_tab";
    265     case NEW_WINDOW:
    266       return "new_window";
    267     case NEW_POPUP:
    268       return "new_popup";
    269     default:
    270       NOTREACHED() << "Unknown Window Open Disposition";
    271       return "ignore";
    272   }
    273 }
    274 
    275 std::string JavaScriptMessageTypeToString(JavaScriptMessageType message_type) {
    276   switch (message_type) {
    277     case JAVASCRIPT_MESSAGE_TYPE_ALERT:
    278       return "alert";
    279     case JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
    280       return "confirm";
    281     case JAVASCRIPT_MESSAGE_TYPE_PROMPT:
    282       return "prompt";
    283     default:
    284       NOTREACHED() << "Unknown JavaScript Message Type.";
    285       return "unknown";
    286   }
    287 }
    288 
    289 // Called on IO thread.
    290 static std::string RetrieveDownloadURLFromRequestId(
    291     RenderViewHost* render_view_host,
    292     int url_request_id) {
    293   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    294 
    295   int render_process_id = render_view_host->GetProcess()->GetID();
    296   GlobalRequestID global_id(render_process_id, url_request_id);
    297   net::URLRequest* url_request =
    298       ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
    299   if (url_request)
    300     return url_request->url().possibly_invalid_spec();
    301   return "";
    302 }
    303 
    304 }  // namespace
    305 
    306 class BrowserPluginGuest::EmbedderWebContentsObserver
    307     : public WebContentsObserver {
    308  public:
    309   explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
    310       : WebContentsObserver(guest->embedder_web_contents()),
    311         browser_plugin_guest_(guest) {
    312   }
    313 
    314   virtual ~EmbedderWebContentsObserver() {
    315   }
    316 
    317   // WebContentsObserver:
    318   virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
    319     browser_plugin_guest_->EmbedderDestroyed();
    320   }
    321 
    322   virtual void WasShown() OVERRIDE {
    323     browser_plugin_guest_->EmbedderVisibilityChanged(true);
    324   }
    325 
    326   virtual void WasHidden() OVERRIDE {
    327     browser_plugin_guest_->EmbedderVisibilityChanged(false);
    328   }
    329 
    330  private:
    331   BrowserPluginGuest* browser_plugin_guest_;
    332 
    333   DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
    334 };
    335 
    336 BrowserPluginGuest::BrowserPluginGuest(
    337     int instance_id,
    338     bool has_render_view,
    339     WebContentsImpl* web_contents,
    340     BrowserPluginGuest* opener)
    341     : WebContentsObserver(web_contents),
    342       weak_ptr_factory_(this),
    343       embedder_web_contents_(NULL),
    344       instance_id_(instance_id),
    345       damage_buffer_sequence_id_(0),
    346       damage_buffer_size_(0),
    347       damage_buffer_scale_factor_(1.0f),
    348       guest_device_scale_factor_(1.0f),
    349       guest_hang_timeout_(
    350           base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
    351       focused_(false),
    352       mouse_locked_(false),
    353       pending_lock_request_(false),
    354       embedder_visible_(true),
    355       copy_request_id_(0),
    356       next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
    357       has_render_view_(has_render_view),
    358       last_seen_auto_size_enabled_(false),
    359       is_in_destruction_(false) {
    360   DCHECK(web_contents);
    361   web_contents->SetDelegate(this);
    362   if (opener)
    363     opener_ = opener->AsWeakPtr();
    364   GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
    365                                                              GetWebContents());
    366 }
    367 
    368 bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
    369                                              int32 level,
    370                                              const base::string16& message,
    371                                              int32 line_no,
    372                                              const base::string16& source_id) {
    373   if (!delegate_)
    374     return false;
    375 
    376   delegate_->AddMessageToConsole(level, message, line_no, source_id);
    377   return true;
    378 }
    379 
    380 void BrowserPluginGuest::DestroyUnattachedWindows() {
    381   // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
    382   // pending_new_windows_ set. To avoid mutating the set while iterating, we
    383   // create a copy of the pending new windows set and iterate over the copy.
    384   PendingWindowMap pending_new_windows(pending_new_windows_);
    385   // Clean up unattached new windows opened by this guest.
    386   for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
    387        it != pending_new_windows.end(); ++it) {
    388     it->first->Destroy();
    389   }
    390   // All pending windows should be removed from the set after Destroy() is
    391   // called on all of them.
    392   DCHECK(pending_new_windows_.empty());
    393 }
    394 
    395 void BrowserPluginGuest::LoadURLWithParams(const GURL& url,
    396                                            const Referrer& referrer,
    397                                            PageTransition transition_type,
    398                                            WebContents* web_contents) {
    399   NavigationController::LoadURLParams load_url_params(url);
    400   load_url_params.referrer = referrer;
    401   load_url_params.transition_type = transition_type;
    402   load_url_params.extra_headers = std::string();
    403   if (delegate_ && delegate_->IsOverridingUserAgent()) {
    404     load_url_params.override_user_agent =
    405         NavigationController::UA_OVERRIDE_TRUE;
    406   }
    407   web_contents->GetController().LoadURLWithParams(load_url_params);
    408 }
    409 
    410 void BrowserPluginGuest::RespondToPermissionRequest(
    411     int request_id,
    412     bool should_allow,
    413     const std::string& user_input) {
    414   RequestMap::iterator request_itr = permission_request_map_.find(request_id);
    415   if (request_itr == permission_request_map_.end()) {
    416     VLOG(0) << "Not a valid request ID.";
    417     return;
    418   }
    419   request_itr->second->Respond(should_allow, user_input);
    420   permission_request_map_.erase(request_itr);
    421 }
    422 
    423 int BrowserPluginGuest::RequestPermission(
    424     BrowserPluginPermissionType permission_type,
    425     scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
    426     const base::DictionaryValue& request_info) {
    427   if (!delegate_) {
    428     request->Respond(false, "");
    429     return browser_plugin::kInvalidPermissionRequestID;
    430   }
    431 
    432   int request_id = ++next_permission_request_id_;
    433   permission_request_map_[request_id] = request;
    434 
    435   BrowserPluginGuestDelegate::PermissionResponseCallback callback =
    436       base::Bind(&BrowserPluginGuest::RespondToPermissionRequest,
    437                   AsWeakPtr(),
    438                   request_id);
    439   // If BrowserPluginGuestDelegate hasn't handled the permission then we simply
    440   // perform the default action (which is one of allow or reject) immediately.
    441   if (!delegate_->RequestPermission(
    442       permission_type, request_info, callback, request->AllowedByDefault())) {
    443     callback.Run(request->AllowedByDefault(), "");
    444     return browser_plugin::kInvalidPermissionRequestID;
    445   }
    446 
    447   return request_id;
    448 }
    449 
    450 BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
    451     const OpenURLParams& params) {
    452   BrowserPluginGuestManager* guest_manager =
    453       GetWebContents()->GetBrowserPluginGuestManager();
    454 
    455   // Allocate a new instance ID for the new guest.
    456   int instance_id = guest_manager->get_next_instance_id();
    457 
    458   // Set the attach params to use the same partition as the opener.
    459   // We pull the partition information from the site's URL, which is of the form
    460   // guest://site/{persist}?{partition_name}.
    461   const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
    462   BrowserPluginHostMsg_Attach_Params attach_params;
    463   attach_params.storage_partition_id = site_url.query();
    464   attach_params.persist_storage =
    465       site_url.path().find("persist") != std::string::npos;
    466 
    467   // The new guest gets a copy of this guest's extra params so that the content
    468   // embedder exposes the same API for this guest as its opener.
    469   scoped_ptr<base::DictionaryValue> extra_params(
    470       extra_attach_params_->DeepCopy());
    471   BrowserPluginGuest* new_guest =
    472       GetWebContents()->GetBrowserPluginGuestManager()->CreateGuest(
    473           GetWebContents()->GetSiteInstance(), instance_id,
    474           attach_params, extra_params.Pass());
    475   new_guest->opener_ = AsWeakPtr();
    476 
    477   // Take ownership of |new_guest|.
    478   pending_new_windows_.insert(
    479       std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
    480 
    481   // Request permission to show the new window.
    482   RequestNewWindowPermission(params.disposition, gfx::Rect(),
    483                              params.user_gesture, new_guest->GetWebContents());
    484 
    485   return new_guest;
    486 }
    487 
    488 void BrowserPluginGuest::EmbedderDestroyed() {
    489   embedder_web_contents_ = NULL;
    490   if (delegate_)
    491     delegate_->EmbedderDestroyed();
    492   Destroy();
    493 }
    494 
    495 void BrowserPluginGuest::Destroy() {
    496   is_in_destruction_ = true;
    497   if (!attached() && opener())
    498     opener()->pending_new_windows_.erase(this);
    499   DestroyUnattachedWindows();
    500   GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_);
    501   delete GetWebContents();
    502 }
    503 
    504 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
    505     const IPC::Message& message) {
    506   bool handled = true;
    507   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
    508     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
    509                         OnSwapBuffersACK)
    510     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
    511                         OnCompositorFrameACK)
    512     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
    513                         OnCopyFromCompositingSurfaceAck)
    514     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
    515                         OnDragStatusUpdate)
    516     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
    517                         OnExecuteEditCommand)
    518     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
    519                         OnExtendSelectionAndDelete)
    520     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
    521                         OnHandleInputEvent)
    522     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
    523                         OnImeConfirmComposition)
    524     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
    525                         OnImeSetComposition)
    526     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
    527     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
    528     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
    529     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
    530                         OnReclaimCompositorResources)
    531     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
    532     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
    533     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
    534                         OnSetEditCommandsForNextKeyEvent)
    535     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
    536     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName)
    537     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
    538                         OnSetContentsOpaque)
    539     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
    540     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
    541     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
    542     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
    543     IPC_MESSAGE_UNHANDLED(handled = false)
    544   IPC_END_MESSAGE_MAP()
    545   return handled;
    546 }
    547 
    548 void BrowserPluginGuest::Initialize(
    549     const BrowserPluginHostMsg_Attach_Params& params,
    550     WebContentsImpl* embedder_web_contents) {
    551   focused_ = params.focused;
    552   guest_visible_ = params.visible;
    553   guest_opaque_ = params.opaque;
    554   guest_window_rect_ = params.resize_guest_params.view_rect;
    555 
    556   if (!params.name.empty())
    557     name_ = params.name;
    558   auto_size_enabled_ = params.auto_size_params.enable;
    559   max_auto_size_ = params.auto_size_params.max_size;
    560   min_auto_size_ = params.auto_size_params.min_size;
    561 
    562   // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
    563   // be attached.
    564   embedder_web_contents_ = embedder_web_contents;
    565 
    566   WebContentsViewGuest* new_view =
    567       static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
    568   new_view->OnGuestInitialized(embedder_web_contents->GetView());
    569 
    570   RendererPreferences* renderer_prefs =
    571       GetWebContents()->GetMutableRendererPrefs();
    572   std::string guest_user_agent_override = renderer_prefs->user_agent_override;
    573   // Copy renderer preferences (and nothing else) from the embedder's
    574   // WebContents to the guest.
    575   //
    576   // For GTK and Aura this is necessary to get proper renderer configuration
    577   // values for caret blinking interval, colors related to selection and
    578   // focus.
    579   *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
    580   renderer_prefs->user_agent_override = guest_user_agent_override;
    581 
    582   // We would like the guest to report changes to frame names so that we can
    583   // update the BrowserPlugin's corresponding 'name' attribute.
    584   // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
    585   renderer_prefs->report_frame_name_changes = true;
    586   // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
    587   // navigations still continue to function inside the app.
    588   renderer_prefs->browser_handles_all_top_level_requests = false;
    589   // Disable "client blocked" error page for browser plugin.
    590   renderer_prefs->disable_client_blocked_error_page = true;
    591 
    592   embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
    593 
    594   OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
    595 
    596   // Create a swapped out RenderView for the guest in the embedder render
    597   // process, so that the embedder can access the guest's window object.
    598   int guest_routing_id =
    599       GetWebContents()->CreateSwappedOutRenderView(
    600           embedder_web_contents_->GetSiteInstance());
    601   SendMessageToEmbedder(
    602       new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
    603                                                    guest_routing_id));
    604 
    605   if (!params.src.empty()) {
    606     // params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
    607     OnNavigateGuest(instance_id_, params.src);
    608   }
    609 
    610   has_render_view_ = true;
    611 
    612   if (!embedder_web_contents_->
    613           GetWebkitPrefs().accelerated_compositing_enabled) {
    614     WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
    615     prefs.accelerated_compositing_enabled = false;
    616     GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
    617   }
    618 
    619   // Enable input method for guest if it's enabled for the embedder.
    620   if (static_cast<RenderViewHostImpl*>(
    621       embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
    622     RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
    623         GetWebContents()->GetRenderViewHost());
    624     guest_rvh->SetInputMethodActive(true);
    625   }
    626 
    627   // Inform the embedder of the guest's information.
    628   // We pull the partition information from the site's URL, which is of the form
    629   // guest://site/{persist}?{partition_name}.
    630   const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
    631   BrowserPluginMsg_Attach_ACK_Params ack_params;
    632   ack_params.storage_partition_id = site_url.query();
    633   ack_params.persist_storage =
    634       site_url.path().find("persist") != std::string::npos;
    635   ack_params.name = name_;
    636   SendMessageToEmbedder(
    637       new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
    638 
    639   if (delegate_)
    640     delegate_->DidAttach();
    641 }
    642 
    643 BrowserPluginGuest::~BrowserPluginGuest() {
    644   while (!pending_messages_.empty()) {
    645     delete pending_messages_.front();
    646     pending_messages_.pop();
    647   }
    648 }
    649 
    650 // static
    651 BrowserPluginGuest* BrowserPluginGuest::Create(
    652     int instance_id,
    653     SiteInstance* guest_site_instance,
    654     WebContentsImpl* web_contents,
    655     scoped_ptr<base::DictionaryValue> extra_params) {
    656   RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
    657   BrowserPluginGuest* guest = NULL;
    658   if (factory_) {
    659     guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents);
    660   } else {
    661     guest = new BrowserPluginGuest(instance_id, false, web_contents, NULL);
    662   }
    663   guest->extra_attach_params_.reset(extra_params->DeepCopy());
    664   web_contents->SetBrowserPluginGuest(guest);
    665   BrowserPluginGuestDelegate* delegate = NULL;
    666   GetContentClient()->browser()->GuestWebContentsCreated(
    667       guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass());
    668   guest->SetDelegate(delegate);
    669   return guest;
    670 }
    671 
    672 // static
    673 BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
    674     int instance_id,
    675     bool has_render_view,
    676     WebContentsImpl* web_contents,
    677     BrowserPluginGuest* opener) {
    678   BrowserPluginGuest* guest =
    679       new BrowserPluginGuest(
    680           instance_id, has_render_view, web_contents, opener);
    681   web_contents->SetBrowserPluginGuest(guest);
    682   BrowserPluginGuestDelegate* delegate = NULL;
    683   GetContentClient()->browser()->GuestWebContentsCreated(
    684       opener->GetWebContents()->GetSiteInstance(),
    685       web_contents, opener->GetWebContents(), &delegate,
    686       scoped_ptr<base::DictionaryValue>());
    687   guest->SetDelegate(delegate);
    688   return guest;
    689 }
    690 
    691 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
    692   return embedder_web_contents_->GetRenderWidgetHostView();
    693 }
    694 
    695 void BrowserPluginGuest::UpdateVisibility() {
    696   OnSetVisibility(instance_id_, visible());
    697 }
    698 
    699 void BrowserPluginGuest::CopyFromCompositingSurface(
    700       gfx::Rect src_subrect,
    701       gfx::Size dst_size,
    702       const base::Callback<void(bool, const SkBitmap&)>& callback) {
    703   copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
    704   SendMessageToEmbedder(
    705       new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
    706           copy_request_id_, src_subrect, dst_size));
    707 }
    708 
    709 // screen.
    710 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
    711   gfx::Rect guest_rect(bounds);
    712   guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
    713   return guest_rect;
    714 }
    715 
    716 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
    717   embedder_visible_ = visible;
    718   UpdateVisibility();
    719 }
    720 
    721 void BrowserPluginGuest::AddNewContents(WebContents* source,
    722                                         WebContents* new_contents,
    723                                         WindowOpenDisposition disposition,
    724                                         const gfx::Rect& initial_pos,
    725                                         bool user_gesture,
    726                                         bool* was_blocked) {
    727   if (was_blocked)
    728     *was_blocked = false;
    729   RequestNewWindowPermission(disposition, initial_pos, user_gesture,
    730                              static_cast<WebContentsImpl*>(new_contents));
    731 }
    732 
    733 void BrowserPluginGuest::CanDownload(
    734     RenderViewHost* render_view_host,
    735     int request_id,
    736     const std::string& request_method,
    737     const base::Callback<void(bool)>& callback) {
    738   BrowserThread::PostTaskAndReplyWithResult(
    739       BrowserThread::IO, FROM_HERE,
    740       base::Bind(&RetrieveDownloadURLFromRequestId,
    741                  render_view_host, request_id),
    742       base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId,
    743                  weak_ptr_factory_.GetWeakPtr(),
    744                  request_method,
    745                  callback));
    746 }
    747 
    748 void BrowserPluginGuest::LoadProgressChanged(WebContents* contents,
    749                                              double progress) {
    750   if (delegate_)
    751     delegate_->LoadProgressed(progress);
    752 }
    753 
    754 void BrowserPluginGuest::CloseContents(WebContents* source) {
    755   if (!delegate_)
    756     return;
    757 
    758   delegate_->Close();
    759 }
    760 
    761 JavaScriptDialogManager* BrowserPluginGuest::GetJavaScriptDialogManager() {
    762   return this;
    763 }
    764 
    765 bool BrowserPluginGuest::HandleContextMenu(const ContextMenuParams& params) {
    766   // TODO(fsamuel): We show the regular page context menu handler for now until
    767   // we implement the Apps Context Menu API for Browser Plugin (see
    768   // http://crbug.com/140315).
    769   return false;  // Will be handled by WebContentsViewGuest.
    770 }
    771 
    772 void BrowserPluginGuest::HandleKeyboardEvent(
    773     WebContents* source,
    774     const NativeWebKeyboardEvent& event) {
    775   if (!attached())
    776     return;
    777 
    778   if (UnlockMouseIfNecessary(event))
    779     return;
    780 
    781   if (delegate_ && delegate_->HandleKeyboardEvent(event))
    782     return;
    783 
    784   if (!embedder_web_contents_->GetDelegate())
    785     return;
    786 
    787   // Send the unhandled keyboard events back to the embedder to reprocess them.
    788   // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
    789   // events because the guest may be arbitrarily delayed when responding to
    790   // keyboard events. In that time, the embedder may have received and processed
    791   // additional key events. This needs to be fixed as soon as possible.
    792   // See http://crbug.com/229882.
    793   embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
    794       web_contents(), event);
    795 }
    796 
    797 WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
    798                                                 const OpenURLParams& params) {
    799   // If the guest wishes to navigate away prior to attachment then we save the
    800   // navigation to perform upon attachment. Navigation initializes a lot of
    801   // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
    802   // Navigation also resumes resource loading which we don't want to allow
    803   // until attachment.
    804   if (!attached()) {
    805     PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
    806     if (it == opener()->pending_new_windows_.end())
    807       return NULL;
    808     const NewWindowInfo& old_target_url = it->second;
    809     NewWindowInfo new_window_info(params.url, old_target_url.name);
    810     new_window_info.changed = new_window_info.url != old_target_url.url;
    811     it->second = new_window_info;
    812     return NULL;
    813   }
    814   if (params.disposition == CURRENT_TAB) {
    815     // This can happen for cross-site redirects.
    816     LoadURLWithParams(params.url, params.referrer, params.transition, source);
    817     return source;
    818   }
    819 
    820   return CreateNewGuestWindow(params)->GetWebContents();
    821 }
    822 
    823 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
    824                                             int64 source_frame_id,
    825                                             const base::string16& frame_name,
    826                                             const GURL& target_url,
    827                                             WebContents* new_contents) {
    828   WebContentsImpl* new_contents_impl =
    829       static_cast<WebContentsImpl*>(new_contents);
    830   BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
    831   guest->opener_ = AsWeakPtr();
    832   std::string guest_name = UTF16ToUTF8(frame_name);
    833   guest->name_ = guest_name;
    834   // Take ownership of the new guest until it is attached to the embedder's DOM
    835   // tree to avoid leaking a guest if this guest is destroyed before attaching
    836   // the new guest.
    837   pending_new_windows_.insert(
    838       std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
    839 }
    840 
    841 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
    842   RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
    843   if (!delegate_)
    844     return;
    845   delegate_->RendererUnresponsive();
    846 }
    847 
    848 void BrowserPluginGuest::RendererResponsive(WebContents* source) {
    849   RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
    850   if (!delegate_)
    851     return;
    852   delegate_->RendererResponsive();
    853 }
    854 
    855 void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
    856                                         const FileChooserParams& params) {
    857   if (!attached())
    858     return;
    859 
    860   if (!embedder_web_contents_->GetDelegate())
    861     return;
    862 
    863   embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
    864 }
    865 
    866 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
    867   // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
    868   // manage the focus ourselves.
    869   return false;
    870 }
    871 
    872 WebContentsImpl* BrowserPluginGuest::GetWebContents() {
    873   return static_cast<WebContentsImpl*>(web_contents());
    874 }
    875 
    876 base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
    877     const BrowserPluginHostMsg_ResizeGuest_Params& params) {
    878   if (!attached()) {
    879     LOG(WARNING) << "Attempting to map a damage buffer prior to attachment.";
    880     return NULL;
    881   }
    882 #if defined(OS_WIN)
    883   base::ProcessHandle handle =
    884       embedder_web_contents_->GetRenderProcessHost()->GetHandle();
    885   scoped_ptr<base::SharedMemory> shared_buf(
    886       new base::SharedMemory(params.damage_buffer_handle, false, handle));
    887 #elif defined(OS_POSIX)
    888   scoped_ptr<base::SharedMemory> shared_buf(
    889       new base::SharedMemory(params.damage_buffer_handle, false));
    890 #endif
    891   if (!shared_buf->Map(params.damage_buffer_size)) {
    892     LOG(WARNING) << "Unable to map the embedder's damage buffer.";
    893     return NULL;
    894   }
    895   return shared_buf.release();
    896 }
    897 
    898 void BrowserPluginGuest::SetDamageBuffer(
    899     const BrowserPluginHostMsg_ResizeGuest_Params& params) {
    900   damage_buffer_.reset(GetDamageBufferFromEmbedder(params));
    901   // Sanity check: Verify that we've correctly shared the damage buffer memory
    902   // between the embedder and browser processes.
    903   DCHECK(!damage_buffer_ ||
    904       *static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef);
    905   damage_buffer_sequence_id_ = params.damage_buffer_sequence_id;
    906   damage_buffer_size_ = params.damage_buffer_size;
    907   damage_view_size_ = params.view_rect.size();
    908   damage_buffer_scale_factor_ = params.scale_factor;
    909 }
    910 
    911 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
    912     const gfx::Point& relative_position) const {
    913   gfx::Point screen_pos(relative_position);
    914   screen_pos += guest_window_rect_.OffsetFromOrigin();
    915   return screen_pos;
    916 }
    917 
    918 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
    919   return size.width() <= max_auto_size_.width() &&
    920       size.height() <= max_auto_size_.height();
    921 }
    922 
    923 void BrowserPluginGuest::RequestNewWindowPermission(
    924     WindowOpenDisposition disposition,
    925     const gfx::Rect& initial_bounds,
    926     bool user_gesture,
    927     WebContentsImpl* new_contents) {
    928   BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
    929   PendingWindowMap::iterator it = pending_new_windows_.find(guest);
    930   if (it == pending_new_windows_.end())
    931     return;
    932   const NewWindowInfo& new_window_info = it->second;
    933 
    934   base::DictionaryValue request_info;
    935   request_info.Set(browser_plugin::kInitialHeight,
    936                    base::Value::CreateIntegerValue(initial_bounds.height()));
    937   request_info.Set(browser_plugin::kInitialWidth,
    938                    base::Value::CreateIntegerValue(initial_bounds.width()));
    939   request_info.Set(browser_plugin::kTargetURL,
    940                    base::Value::CreateStringValue(new_window_info.url.spec()));
    941   request_info.Set(browser_plugin::kName,
    942                    base::Value::CreateStringValue(new_window_info.name));
    943   request_info.Set(browser_plugin::kWindowID,
    944                    base::Value::CreateIntegerValue(guest->instance_id()));
    945   request_info.Set(browser_plugin::kWindowOpenDisposition,
    946                    base::Value::CreateStringValue(
    947                        WindowOpenDispositionToString(disposition)));
    948 
    949   RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
    950                     new NewWindowRequest(guest->instance_id(), this),
    951                     request_info);
    952 }
    953 
    954 bool BrowserPluginGuest::UnlockMouseIfNecessary(
    955     const NativeWebKeyboardEvent& event) {
    956   if (!mouse_locked_)
    957     return false;
    958 
    959   embedder_web_contents()->GotResponseToLockMouseRequest(false);
    960   return true;
    961 }
    962 
    963 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
    964   if (!attached()) {
    965     // Some pages such as data URLs, javascript URLs, and about:blank
    966     // do not load external resources and so they load prior to attachment.
    967     // As a result, we must save all these IPCs until attachment and then
    968     // forward them so that the embedder gets a chance to see and process
    969     // the load events.
    970     pending_messages_.push(msg);
    971     return;
    972   }
    973   msg->set_routing_id(embedder_web_contents_->GetRoutingID());
    974   embedder_web_contents_->Send(msg);
    975 }
    976 
    977 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
    978     int screen_x, int screen_y, blink::WebDragOperation operation) {
    979   web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
    980       screen_x, screen_y, operation);
    981 }
    982 
    983 void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y,
    984                                            int screen_x, int screen_y) {
    985   web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y,
    986                                                          screen_x, screen_y);
    987 }
    988 
    989 void BrowserPluginGuest::EndSystemDrag() {
    990   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
    991       GetWebContents()->GetRenderViewHost());
    992   guest_rvh->DragSourceSystemDragEnded();
    993   // Issue a MouseUp event to get out of a selection state.
    994   blink::WebMouseEvent mouse_event;
    995   mouse_event.type = blink::WebInputEvent::MouseUp;
    996   mouse_event.button = blink::WebMouseEvent::ButtonLeft;
    997   guest_rvh->ForwardMouseEvent(mouse_event);
    998 }
    999 
   1000 void BrowserPluginGuest::SetDelegate(BrowserPluginGuestDelegate* delegate) {
   1001   DCHECK(!delegate_);
   1002   delegate_.reset(delegate);
   1003 }
   1004 
   1005 void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
   1006     int bridge_id,
   1007     const GURL& requesting_frame,
   1008     const GeolocationCallback& callback) {
   1009   base::DictionaryValue request_info;
   1010   request_info.Set(browser_plugin::kURL,
   1011                    base::Value::CreateStringValue(requesting_frame.spec()));
   1012 
   1013   int request_id =
   1014       RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION,
   1015                         new GeolocationRequest(
   1016                             callback, bridge_id, &weak_ptr_factory_),
   1017                         request_info);
   1018 
   1019   DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
   1020          bridge_id_to_request_id_map_.end());
   1021   bridge_id_to_request_id_map_[bridge_id] = request_id;
   1022 }
   1023 
   1024 int BrowserPluginGuest::RemoveBridgeID(int bridge_id) {
   1025   std::map<int, int>::iterator bridge_itr =
   1026       bridge_id_to_request_id_map_.find(bridge_id);
   1027   if (bridge_itr == bridge_id_to_request_id_map_.end())
   1028     return browser_plugin::kInvalidPermissionRequestID;
   1029 
   1030   int request_id = bridge_itr->second;
   1031   bridge_id_to_request_id_map_.erase(bridge_itr);
   1032   return request_id;
   1033 }
   1034 
   1035 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
   1036   int request_id = RemoveBridgeID(bridge_id);
   1037   RequestMap::iterator request_itr = permission_request_map_.find(request_id);
   1038   if (request_itr == permission_request_map_.end())
   1039     return;
   1040   permission_request_map_.erase(request_itr);
   1041 }
   1042 
   1043 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
   1044                                                   int bridge_id,
   1045                                                   bool allowed) {
   1046   callback.Run(allowed);
   1047   RemoveBridgeID(bridge_id);
   1048 }
   1049 
   1050 void BrowserPluginGuest::SendQueuedMessages() {
   1051   if (!attached())
   1052     return;
   1053 
   1054   while (!pending_messages_.empty()) {
   1055     IPC::Message* message = pending_messages_.front();
   1056     pending_messages_.pop();
   1057     SendMessageToEmbedder(message);
   1058   }
   1059 }
   1060 
   1061 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
   1062     int64 frame_id,
   1063     const base::string16& frame_unique_name,
   1064     bool is_main_frame,
   1065     const GURL& url,
   1066     PageTransition transition_type,
   1067     RenderViewHost* render_view_host) {
   1068   RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
   1069 }
   1070 
   1071 void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
   1072   bool enable_dragdrop = delegate_ && delegate_->IsDragAndDropEnabled();
   1073   if (!enable_dragdrop) {
   1074     // Initiating a drag from inside a guest is currently not supported without
   1075     // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
   1076     // JS to disable it. http://crbug.com/161112
   1077     const char script[] = "window.addEventListener('dragstart', function() { "
   1078                           "  window.event.preventDefault(); "
   1079                           "});";
   1080     render_view_host->ExecuteJavascriptInWebFrame(base::string16(),
   1081                                                   ASCIIToUTF16(script));
   1082   }
   1083 }
   1084 
   1085 void BrowserPluginGuest::RenderViewReady() {
   1086   RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
   1087   // The guest RenderView should always live in a guest process.
   1088   CHECK(rvh->GetProcess()->IsGuest());
   1089   // TODO(fsamuel): Investigate whether it's possible to update state earlier
   1090   // here (see http://crbug.com/158151).
   1091   Send(new InputMsg_SetFocus(routing_id(), focused_));
   1092   UpdateVisibility();
   1093   if (auto_size_enabled_)
   1094     rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
   1095   else
   1096     rvh->DisableAutoResize(damage_view_size_);
   1097 
   1098   Send(new ViewMsg_SetName(routing_id(), name_));
   1099   OnSetContentsOpaque(instance_id_, guest_opaque_);
   1100 
   1101   RenderWidgetHostImpl::From(rvh)->
   1102       set_hung_renderer_delay_ms(guest_hang_timeout_);
   1103 }
   1104 
   1105 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
   1106   SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
   1107   switch (status) {
   1108     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
   1109       RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
   1110       break;
   1111     case base::TERMINATION_STATUS_PROCESS_CRASHED:
   1112       RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
   1113       break;
   1114     case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
   1115       RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
   1116       break;
   1117     default:
   1118       break;
   1119   }
   1120   // TODO(fsamuel): Consider whether we should be clearing
   1121   // |permission_request_map_| here.
   1122   if (delegate_)
   1123     delegate_->GuestProcessGone(status);
   1124 }
   1125 
   1126 // static
   1127 void BrowserPluginGuest::AcknowledgeBufferPresent(
   1128     int route_id,
   1129     int gpu_host_id,
   1130     const std::string& mailbox_name,
   1131     uint32 sync_point) {
   1132   AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
   1133   ack_params.mailbox_name = mailbox_name;
   1134   ack_params.sync_point = sync_point;
   1135   RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id,
   1136                                                  gpu_host_id,
   1137                                                  ack_params);
   1138 }
   1139 
   1140 // static
   1141 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
   1142     const IPC::Message& message) {
   1143   switch (message.type()) {
   1144     case BrowserPluginHostMsg_BuffersSwappedACK::ID:
   1145     case BrowserPluginHostMsg_CompositorFrameACK::ID:
   1146     case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
   1147     case BrowserPluginHostMsg_DragStatusUpdate::ID:
   1148     case BrowserPluginHostMsg_ExecuteEditCommand::ID:
   1149     case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
   1150     case BrowserPluginHostMsg_HandleInputEvent::ID:
   1151     case BrowserPluginHostMsg_ImeConfirmComposition::ID:
   1152     case BrowserPluginHostMsg_ImeSetComposition::ID:
   1153     case BrowserPluginHostMsg_LockMouse_ACK::ID:
   1154     case BrowserPluginHostMsg_NavigateGuest::ID:
   1155     case BrowserPluginHostMsg_PluginDestroyed::ID:
   1156     case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
   1157     case BrowserPluginHostMsg_ResizeGuest::ID:
   1158     case BrowserPluginHostMsg_SetAutoSize::ID:
   1159     case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
   1160     case BrowserPluginHostMsg_SetFocus::ID:
   1161     case BrowserPluginHostMsg_SetName::ID:
   1162     case BrowserPluginHostMsg_SetContentsOpaque::ID:
   1163     case BrowserPluginHostMsg_SetVisibility::ID:
   1164     case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
   1165     case BrowserPluginHostMsg_UpdateGeometry::ID:
   1166     case BrowserPluginHostMsg_UpdateRect_ACK::ID:
   1167       return true;
   1168     default:
   1169       return false;
   1170   }
   1171 }
   1172 
   1173 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
   1174   bool handled = true;
   1175   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
   1176     IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
   1177                         OnHasTouchEventHandlers)
   1178     IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
   1179     IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
   1180  #if defined(OS_MACOSX)
   1181     // MacOSX creates and populates platform-specific select drop-down menus
   1182     // whereas other platforms merely create a popup window that the guest
   1183     // renderer process paints inside.
   1184     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
   1185  #endif
   1186     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
   1187     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
   1188     IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
   1189                         OnTextInputTypeChanged)
   1190     IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
   1191                         OnImeCancelComposition)
   1192 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   1193     IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
   1194                         OnImeCompositionRangeChanged)
   1195 #endif
   1196     IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
   1197     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
   1198     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
   1199     IPC_MESSAGE_UNHANDLED(handled = false)
   1200   IPC_END_MESSAGE_MAP()
   1201   return handled;
   1202 }
   1203 
   1204 void BrowserPluginGuest::Attach(
   1205     WebContentsImpl* embedder_web_contents,
   1206     BrowserPluginHostMsg_Attach_Params params,
   1207     const base::DictionaryValue& extra_params) {
   1208   if (attached())
   1209     return;
   1210 
   1211   extra_attach_params_.reset(extra_params.DeepCopy());
   1212 
   1213   // Clear parameters that get inherited from the opener.
   1214   params.storage_partition_id.clear();
   1215   params.persist_storage = false;
   1216   params.src.clear();
   1217 
   1218   // If a RenderView has already been created for this new window, then we need
   1219   // to initialize the browser-side state now so that the RenderFrameHostManager
   1220   // does not create a new RenderView on navigation.
   1221   if (has_render_view_) {
   1222     static_cast<RenderViewHostImpl*>(
   1223         GetWebContents()->GetRenderViewHost())->Init();
   1224     WebContentsViewGuest* new_view =
   1225         static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
   1226     new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
   1227   }
   1228 
   1229   // We need to do a navigation here if the target URL has changed between
   1230   // the time the WebContents was created and the time it was attached.
   1231   // We also need to do an initial navigation if a RenderView was never
   1232   // created for the new window in cases where there is no referrer.
   1233   PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
   1234   if (it != opener()->pending_new_windows_.end()) {
   1235     const NewWindowInfo& new_window_info = it->second;
   1236     if (new_window_info.changed || !has_render_view_)
   1237       params.src = it->second.url.spec();
   1238   } else {
   1239     NOTREACHED();
   1240   }
   1241 
   1242   // Once a new guest is attached to the DOM of the embedder page, then the
   1243   // lifetime of the new guest is no longer managed by the opener guest.
   1244   opener()->pending_new_windows_.erase(this);
   1245 
   1246   // The guest's frame name takes precedence over the BrowserPlugin's name.
   1247   // The guest's frame name is assigned in
   1248   // BrowserPluginGuest::WebContentsCreated.
   1249   if (!name_.empty())
   1250     params.name.clear();
   1251 
   1252   Initialize(params, embedder_web_contents);
   1253 
   1254   SendQueuedMessages();
   1255 
   1256   RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached"));
   1257 }
   1258 
   1259 void BrowserPluginGuest::OnCompositorFrameACK(
   1260     int instance_id,
   1261     int route_id,
   1262     uint32 output_surface_id,
   1263     int renderer_host_id,
   1264     const cc::CompositorFrameAck& ack) {
   1265   RenderWidgetHostImpl::SendSwapCompositorFrameAck(route_id,
   1266                                                    output_surface_id,
   1267                                                    renderer_host_id,
   1268                                                    ack);
   1269 }
   1270 
   1271 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
   1272                                             blink::WebDragStatus drag_status,
   1273                                             const DropData& drop_data,
   1274                                             blink::WebDragOperationsMask mask,
   1275                                             const gfx::Point& location) {
   1276   RenderViewHost* host = GetWebContents()->GetRenderViewHost();
   1277   switch (drag_status) {
   1278     case blink::WebDragStatusEnter:
   1279       embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
   1280           this);
   1281       host->DragTargetDragEnter(drop_data, location, location, mask, 0);
   1282       break;
   1283     case blink::WebDragStatusOver:
   1284       host->DragTargetDragOver(location, location, mask, 0);
   1285       break;
   1286     case blink::WebDragStatusLeave:
   1287       embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
   1288       host->DragTargetDragLeave();
   1289       break;
   1290     case blink::WebDragStatusDrop:
   1291       host->DragTargetDrop(location, location, 0);
   1292       EndSystemDrag();
   1293       break;
   1294     case blink::WebDragStatusUnknown:
   1295       NOTREACHED();
   1296   }
   1297 }
   1298 
   1299 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
   1300                                               const std::string& name) {
   1301   Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
   1302 }
   1303 
   1304 void BrowserPluginGuest::OnImeSetComposition(
   1305     int instance_id,
   1306     const std::string& text,
   1307     const std::vector<blink::WebCompositionUnderline>& underlines,
   1308     int selection_start,
   1309     int selection_end) {
   1310   Send(new ViewMsg_ImeSetComposition(routing_id(),
   1311                                      UTF8ToUTF16(text), underlines,
   1312                                      selection_start, selection_end));
   1313 }
   1314 
   1315 void BrowserPluginGuest::OnImeConfirmComposition(
   1316     int instance_id,
   1317     const std::string& text,
   1318     bool keep_selection) {
   1319   Send(new ViewMsg_ImeConfirmComposition(routing_id(),
   1320                                          UTF8ToUTF16(text),
   1321                                          gfx::Range::InvalidRange(),
   1322                                          keep_selection));
   1323 }
   1324 
   1325 void BrowserPluginGuest::OnExtendSelectionAndDelete(
   1326     int instance_id,
   1327     int before,
   1328     int after) {
   1329   Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after));
   1330 }
   1331 
   1332 void BrowserPluginGuest::OnReclaimCompositorResources(
   1333     int instance_id,
   1334     int route_id,
   1335     uint32 output_surface_id,
   1336     int renderer_host_id,
   1337     const cc::CompositorFrameAck& ack) {
   1338   RenderWidgetHostImpl::SendReclaimCompositorResources(route_id,
   1339                                                        output_surface_id,
   1340                                                        renderer_host_id,
   1341                                                        ack);
   1342 }
   1343 
   1344 void BrowserPluginGuest::OnHandleInputEvent(
   1345     int instance_id,
   1346     const gfx::Rect& guest_window_rect,
   1347     const blink::WebInputEvent* event) {
   1348   guest_window_rect_ = guest_window_rect;
   1349   // If the embedder's RWHV is destroyed then that means that the embedder's
   1350   // window has been closed but the embedder's WebContents has not yet been
   1351   // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
   1352   // if there is a visible embedder.
   1353   if (embedder_web_contents_->GetRenderWidgetHostView()) {
   1354     guest_screen_rect_ = guest_window_rect;
   1355     guest_screen_rect_.Offset(
   1356         embedder_web_contents_->GetRenderWidgetHostView()->
   1357             GetViewBounds().OffsetFromOrigin());
   1358   }
   1359   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
   1360       GetWebContents()->GetRenderViewHost());
   1361 
   1362   if (blink::WebInputEvent::isMouseEventType(event->type)) {
   1363     guest_rvh->ForwardMouseEvent(
   1364         *static_cast<const blink::WebMouseEvent*>(event));
   1365     return;
   1366   }
   1367 
   1368   if (event->type == blink::WebInputEvent::MouseWheel) {
   1369     guest_rvh->ForwardWheelEvent(
   1370         *static_cast<const blink::WebMouseWheelEvent*>(event));
   1371     return;
   1372   }
   1373 
   1374   if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
   1375     RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
   1376         embedder_web_contents_->GetRenderViewHost());
   1377     if (!embedder_rvh->GetLastKeyboardEvent())
   1378       return;
   1379     NativeWebKeyboardEvent keyboard_event(
   1380         *embedder_rvh->GetLastKeyboardEvent());
   1381     guest_rvh->ForwardKeyboardEvent(keyboard_event);
   1382     return;
   1383   }
   1384 
   1385   if (blink::WebInputEvent::isTouchEventType(event->type)) {
   1386     guest_rvh->ForwardTouchEventWithLatencyInfo(
   1387         *static_cast<const blink::WebTouchEvent*>(event),
   1388         ui::LatencyInfo());
   1389     return;
   1390   }
   1391 
   1392   if (blink::WebInputEvent::isGestureEventType(event->type)) {
   1393     guest_rvh->ForwardGestureEvent(
   1394         *static_cast<const blink::WebGestureEvent*>(event));
   1395     return;
   1396   }
   1397 }
   1398 
   1399 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
   1400                                      bool last_unlocked_by_target,
   1401                                      bool privileged) {
   1402   if (pending_lock_request_) {
   1403     // Immediately reject the lock because only one pointerLock may be active
   1404     // at a time.
   1405     Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
   1406     return;
   1407   }
   1408   pending_lock_request_ = true;
   1409   base::DictionaryValue request_info;
   1410   request_info.Set(browser_plugin::kUserGesture,
   1411                    base::Value::CreateBooleanValue(user_gesture));
   1412   request_info.Set(browser_plugin::kLastUnlockedBySelf,
   1413                    base::Value::CreateBooleanValue(last_unlocked_by_target));
   1414   request_info.Set(browser_plugin::kURL,
   1415                    base::Value::CreateStringValue(
   1416                        web_contents()->GetLastCommittedURL().spec()));
   1417 
   1418   RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
   1419                     new PointerLockRequest(this),
   1420                     request_info);
   1421 }
   1422 
   1423 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
   1424   Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
   1425   pending_lock_request_ = false;
   1426   if (succeeded)
   1427     mouse_locked_ = true;
   1428 }
   1429 
   1430 void BrowserPluginGuest::OnNavigateGuest(
   1431     int instance_id,
   1432     const std::string& src) {
   1433   GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src);
   1434   // We do not load empty urls in web_contents.
   1435   // If a guest sets empty src attribute after it has navigated to some
   1436   // non-empty page, the action is considered no-op. This empty src navigation
   1437   // should never be sent to BrowserPluginGuest (browser process).
   1438   DCHECK(!src.empty());
   1439   if (src.empty())
   1440     return;
   1441 
   1442   // Do not allow navigating a guest to schemes other than known safe schemes.
   1443   // This will block the embedder trying to load unwanted schemes, e.g.
   1444   // chrome://settings.
   1445   bool scheme_is_blocked =
   1446       (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
   1447           url.scheme()) &&
   1448       !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
   1449           url.scheme())) ||
   1450       url.SchemeIs(kJavaScriptScheme);
   1451   if (scheme_is_blocked || !url.is_valid()) {
   1452     if (delegate_) {
   1453       std::string error_type;
   1454       base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
   1455                         &error_type);
   1456       delegate_->LoadAbort(true /* is_top_level */, url, error_type);
   1457     }
   1458     return;
   1459   }
   1460 
   1461   GURL validated_url(url);
   1462   RenderViewHost::FilterURL(
   1463       GetWebContents()->GetRenderProcessHost(),
   1464       false,
   1465       &validated_url);
   1466   // As guests do not swap processes on navigation, only navigations to
   1467   // normal web URLs are supported.  No protocol handlers are installed for
   1468   // other schemes (e.g., WebUI or extensions), and no permissions or bindings
   1469   // can be granted to the guest process.
   1470   LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL,
   1471                     GetWebContents());
   1472 }
   1473 
   1474 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
   1475   Destroy();
   1476 }
   1477 
   1478 void BrowserPluginGuest::OnResizeGuest(
   1479     int instance_id,
   1480     const BrowserPluginHostMsg_ResizeGuest_Params& params) {
   1481   if (!params.size_changed)
   1482     return;
   1483   // BrowserPlugin manages resize flow control itself and does not depend
   1484   // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
   1485   // here. If we are setting the size for the first time before navigating then
   1486   // BrowserPluginGuest does not yet have a RenderViewHost.
   1487   if (GetWebContents()->GetRenderViewHost()) {
   1488     RenderWidgetHostImpl* render_widget_host =
   1489         RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
   1490     render_widget_host->ResetSizeAndRepaintPendingFlags();
   1491 
   1492     if (guest_device_scale_factor_ != params.scale_factor) {
   1493       guest_device_scale_factor_ = params.scale_factor;
   1494       render_widget_host->NotifyScreenInfoChanged();
   1495     }
   1496   }
   1497   // When autosize is turned off and as a result there is a layout change, we
   1498   // send a sizechanged event.
   1499   if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
   1500       !params.view_rect.size().IsEmpty() && delegate_) {
   1501     delegate_->SizeChanged(last_seen_view_size_, params.view_rect.size());
   1502     last_seen_auto_size_enabled_ = false;
   1503   }
   1504   // Invalid damage buffer means we are in HW compositing mode,
   1505   // so just resize the WebContents and repaint if needed.
   1506   if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle))
   1507     SetDamageBuffer(params);
   1508   if (!params.view_rect.size().IsEmpty())
   1509     GetWebContents()->GetView()->SizeContents(params.view_rect.size());
   1510   if (params.repaint)
   1511     Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
   1512 }
   1513 
   1514 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
   1515   if (focused_ == focused)
   1516       return;
   1517   focused_ = focused;
   1518   Send(new InputMsg_SetFocus(routing_id(), focused));
   1519   if (!focused && mouse_locked_)
   1520     OnUnlockMouse();
   1521 }
   1522 
   1523 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
   1524   if (name == name_)
   1525     return;
   1526   name_ = name;
   1527   Send(new ViewMsg_SetName(routing_id(), name));
   1528 }
   1529 
   1530 void BrowserPluginGuest::OnSetSize(
   1531     int instance_id,
   1532     const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
   1533     const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
   1534   bool old_auto_size_enabled = auto_size_enabled_;
   1535   gfx::Size old_max_size = max_auto_size_;
   1536   gfx::Size old_min_size = min_auto_size_;
   1537   auto_size_enabled_ = auto_size_params.enable;
   1538   max_auto_size_ = auto_size_params.max_size;
   1539   min_auto_size_ = auto_size_params.min_size;
   1540   if (auto_size_enabled_ && (!old_auto_size_enabled ||
   1541                              (old_max_size != max_auto_size_) ||
   1542                              (old_min_size != min_auto_size_))) {
   1543     RecordAction(UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
   1544     GetWebContents()->GetRenderViewHost()->EnableAutoResize(
   1545         min_auto_size_, max_auto_size_);
   1546     // TODO(fsamuel): If we're changing autosize parameters, then we force
   1547     // the guest to completely repaint itself, because BrowserPlugin has
   1548     // allocated a new damage buffer and expects a full frame of pixels.
   1549     // Ideally, we shouldn't need to do this because we shouldn't need to
   1550     // allocate a new damage buffer unless |max_auto_size_| has changed.
   1551     // However, even in that case, layout may not change and so we may
   1552     // not get a full frame worth of pixels.
   1553     Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
   1554   } else if (!auto_size_enabled_ && old_auto_size_enabled) {
   1555     GetWebContents()->GetRenderViewHost()->DisableAutoResize(
   1556         resize_guest_params.view_rect.size());
   1557   }
   1558   OnResizeGuest(instance_id_, resize_guest_params);
   1559 }
   1560 
   1561 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
   1562     int instance_id,
   1563     const std::vector<EditCommand>& edit_commands) {
   1564   Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
   1565                                                    edit_commands));
   1566 }
   1567 
   1568 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
   1569   guest_opaque_ = opaque;
   1570 
   1571   SkBitmap background;
   1572   if (!guest_opaque_) {
   1573     background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
   1574     unsigned int color = 0;
   1575     background.setPixels(&color);
   1576   }
   1577   Send(new ViewMsg_SetBackground(routing_id(), background));
   1578 }
   1579 
   1580 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
   1581   guest_visible_ = visible;
   1582   if (embedder_visible_ && guest_visible_)
   1583     GetWebContents()->WasShown();
   1584   else
   1585     GetWebContents()->WasHidden();
   1586 }
   1587 
   1588 void BrowserPluginGuest::OnSwapBuffersACK(int instance_id,
   1589                                           int route_id,
   1590                                           int gpu_host_id,
   1591                                           const std::string& mailbox_name,
   1592                                           uint32 sync_point) {
   1593   AcknowledgeBufferPresent(route_id, gpu_host_id, mailbox_name, sync_point);
   1594 
   1595 // This is only relevant on MACOSX and WIN when threaded compositing
   1596 // is not enabled. In threaded mode, above ACK is sufficient.
   1597 #if defined(OS_MACOSX) || defined(OS_WIN)
   1598   RenderWidgetHostImpl* render_widget_host =
   1599         RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
   1600   render_widget_host->AcknowledgeSwapBuffersToRenderer();
   1601 #endif  // defined(OS_MACOSX) || defined(OS_WIN)
   1602 }
   1603 
   1604 void BrowserPluginGuest::OnUnlockMouse() {
   1605   SendMessageToEmbedder(
   1606       new BrowserPluginMsg_SetMouseLock(instance_id(), false));
   1607 }
   1608 
   1609 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
   1610   // mouse_locked_ could be false here if the lock attempt was cancelled due
   1611   // to window focus, or for various other reasons before the guest was informed
   1612   // of the lock's success.
   1613   if (mouse_locked_)
   1614     Send(new ViewMsg_MouseLockLost(routing_id()));
   1615   mouse_locked_ = false;
   1616 }
   1617 
   1618 void BrowserPluginGuest::OnUpdateRectACK(
   1619     int instance_id,
   1620     bool needs_ack,
   1621     const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
   1622     const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
   1623   // Only the software path expects an ACK.
   1624   if (needs_ack)
   1625     Send(new ViewMsg_UpdateRect_ACK(routing_id()));
   1626   OnSetSize(instance_id_, auto_size_params, resize_guest_params);
   1627 }
   1628 
   1629 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
   1630     int instance_id,
   1631     int request_id,
   1632     const SkBitmap& bitmap) {
   1633   CHECK(copy_request_callbacks_.count(request_id));
   1634   if (!copy_request_callbacks_.count(request_id))
   1635     return;
   1636   const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
   1637   callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
   1638   copy_request_callbacks_.erase(request_id);
   1639 }
   1640 
   1641 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
   1642                                           const gfx::Rect& view_rect) {
   1643   // The plugin has moved within the embedder without resizing or the
   1644   // embedder/container's view rect changing.
   1645   guest_window_rect_ = view_rect;
   1646   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
   1647       GetWebContents()->GetRenderViewHost());
   1648   if (rvh)
   1649     rvh->SendScreenRects();
   1650 }
   1651 
   1652 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
   1653   SendMessageToEmbedder(
   1654       new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
   1655 }
   1656 
   1657 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
   1658   SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
   1659 }
   1660 
   1661 #if defined(OS_MACOSX)
   1662 void BrowserPluginGuest::OnShowPopup(
   1663     const ViewHostMsg_ShowPopup_Params& params) {
   1664   gfx::Rect translated_bounds(params.bounds);
   1665   translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
   1666   BrowserPluginPopupMenuHelper popup_menu_helper(
   1667       embedder_web_contents_->GetRenderViewHost(),
   1668       GetWebContents()->GetRenderViewHost());
   1669   popup_menu_helper.ShowPopupMenu(translated_bounds,
   1670                                   params.item_height,
   1671                                   params.item_font_size,
   1672                                   params.selected_item,
   1673                                   params.popup_items,
   1674                                   params.right_aligned,
   1675                                   params.allow_multiple_selection);
   1676 }
   1677 #endif
   1678 
   1679 void BrowserPluginGuest::OnShowWidget(int route_id,
   1680                                       const gfx::Rect& initial_pos) {
   1681   GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
   1682 }
   1683 
   1684 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
   1685   SendMessageToEmbedder(
   1686       new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
   1687 }
   1688 
   1689 void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
   1690                                            bool is_top_level,
   1691                                            const std::string& name) {
   1692   if (!is_top_level)
   1693     return;
   1694 
   1695   name_ = name;
   1696   SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name));
   1697 }
   1698 
   1699 void BrowserPluginGuest::RequestMediaAccessPermission(
   1700     WebContents* web_contents,
   1701     const MediaStreamRequest& request,
   1702     const MediaResponseCallback& callback) {
   1703   base::DictionaryValue request_info;
   1704   request_info.Set(
   1705       browser_plugin::kURL,
   1706       base::Value::CreateStringValue(request.security_origin.spec()));
   1707 
   1708   RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA,
   1709                     new MediaRequest(request, callback, this),
   1710                     request_info);
   1711 }
   1712 
   1713 void BrowserPluginGuest::RunJavaScriptDialog(
   1714     WebContents* web_contents,
   1715     const GURL& origin_url,
   1716     const std::string& accept_lang,
   1717     JavaScriptMessageType javascript_message_type,
   1718     const base::string16& message_text,
   1719     const base::string16& default_prompt_text,
   1720     const DialogClosedCallback& callback,
   1721     bool* did_suppress_message) {
   1722   base::DictionaryValue request_info;
   1723   request_info.Set(
   1724       browser_plugin::kDefaultPromptText,
   1725       base::Value::CreateStringValue(UTF16ToUTF8(default_prompt_text)));
   1726   request_info.Set(
   1727       browser_plugin::kMessageText,
   1728       base::Value::CreateStringValue(UTF16ToUTF8(message_text)));
   1729   request_info.Set(
   1730       browser_plugin::kMessageType,
   1731       base::Value::CreateStringValue(
   1732           JavaScriptMessageTypeToString(javascript_message_type)));
   1733   request_info.Set(
   1734       browser_plugin::kURL,
   1735       base::Value::CreateStringValue(origin_url.spec()));
   1736 
   1737   RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
   1738                     new JavaScriptDialogRequest(callback),
   1739                     request_info);
   1740 }
   1741 
   1742 void BrowserPluginGuest::RunBeforeUnloadDialog(
   1743     WebContents* web_contents,
   1744     const base::string16& message_text,
   1745     bool is_reload,
   1746     const DialogClosedCallback& callback) {
   1747   // This is called if the guest has a beforeunload event handler.
   1748   // This callback allows navigation to proceed.
   1749   callback.Run(true, base::string16());
   1750 }
   1751 
   1752 bool BrowserPluginGuest::HandleJavaScriptDialog(
   1753     WebContents* web_contents,
   1754     bool accept,
   1755     const base::string16* prompt_override) {
   1756   return false;
   1757 }
   1758 
   1759 void BrowserPluginGuest::CancelActiveAndPendingDialogs(
   1760     WebContents* web_contents) {
   1761 }
   1762 
   1763 void BrowserPluginGuest::WebContentsDestroyed(WebContents* web_contents) {
   1764 }
   1765 
   1766 void BrowserPluginGuest::OnUpdateRect(
   1767     const ViewHostMsg_UpdateRect_Params& params) {
   1768   BrowserPluginMsg_UpdateRect_Params relay_params;
   1769   relay_params.view_size = params.view_size;
   1770   relay_params.scale_factor = params.scale_factor;
   1771   relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
   1772       params.flags);
   1773   relay_params.needs_ack = params.needs_ack;
   1774 
   1775   bool size_changed = last_seen_view_size_ != params.view_size;
   1776   gfx::Size old_size = last_seen_view_size_;
   1777   last_seen_view_size_ = params.view_size;
   1778 
   1779   if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
   1780       size_changed && delegate_) {
   1781     delegate_->SizeChanged(old_size, last_seen_view_size_);
   1782   }
   1783   last_seen_auto_size_enabled_ = auto_size_enabled_;
   1784 
   1785   // HW accelerated case, acknowledge resize only
   1786   if (!params.needs_ack || !damage_buffer_) {
   1787     relay_params.damage_buffer_sequence_id = 0;
   1788     SendMessageToEmbedder(
   1789         new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
   1790     return;
   1791   }
   1792 
   1793   // Only copy damage if the guest is in autosize mode and the guest's view size
   1794   // is less than the maximum size or the guest's view size is equal to the
   1795   // damage buffer's size and the guest's scale factor is equal to the damage
   1796   // buffer's scale factor.
   1797   // The scaling change can happen due to asynchronous updates of the DPI on a
   1798   // resolution change.
   1799   if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
   1800       (params.view_size == damage_view_size())) &&
   1801        params.scale_factor == damage_buffer_scale_factor()) {
   1802     TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
   1803         GetTransportDIB(params.bitmap);
   1804     if (dib) {
   1805       size_t guest_damage_buffer_size =
   1806 #if defined(OS_WIN)
   1807           params.bitmap_rect.width() *
   1808           params.bitmap_rect.height() * 4;
   1809 #else
   1810           dib->size();
   1811 #endif
   1812       size_t embedder_damage_buffer_size = damage_buffer_size_;
   1813       void* guest_memory = dib->memory();
   1814       void* embedder_memory = damage_buffer_->memory();
   1815       size_t size = std::min(guest_damage_buffer_size,
   1816                              embedder_damage_buffer_size);
   1817       memcpy(embedder_memory, guest_memory, size);
   1818     }
   1819   }
   1820   relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_;
   1821   relay_params.bitmap_rect = params.bitmap_rect;
   1822   relay_params.scroll_delta = params.scroll_delta;
   1823   relay_params.scroll_rect = params.scroll_rect;
   1824   relay_params.copy_rects = params.copy_rects;
   1825 
   1826   SendMessageToEmbedder(
   1827       new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
   1828 }
   1829 
   1830 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
   1831                                                 ui::TextInputMode input_mode,
   1832                                                 bool can_compose_inline) {
   1833   RenderWidgetHostViewPort::FromRWHV(
   1834       web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
   1835           type, input_mode, can_compose_inline);
   1836 }
   1837 
   1838 void BrowserPluginGuest::OnImeCancelComposition() {
   1839   RenderWidgetHostViewPort::FromRWHV(
   1840       web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
   1841 }
   1842 
   1843 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   1844 void BrowserPluginGuest::OnImeCompositionRangeChanged(
   1845       const gfx::Range& range,
   1846       const std::vector<gfx::Rect>& character_bounds) {
   1847   RenderWidgetHostViewPort::FromRWHV(
   1848       web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
   1849           range, character_bounds);
   1850 }
   1851 #endif
   1852 
   1853 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
   1854     const std::string& request_method,
   1855     const base::Callback<void(bool)>& callback,
   1856     const std::string& url) {
   1857   if (url.empty()) {
   1858     callback.Run(false);
   1859     return;
   1860   }
   1861 
   1862   base::DictionaryValue request_info;
   1863   request_info.Set(browser_plugin::kRequestMethod,
   1864                    base::Value::CreateStringValue(request_method));
   1865   request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
   1866 
   1867   RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD,
   1868                     new DownloadRequest(callback),
   1869                     request_info);
   1870 }
   1871 
   1872 }  // namespace content
   1873