Home | History | Annotate | Download | only in npapi
      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/renderer/npapi/webplugin_delegate_proxy.h"
      6 
      7 #if defined(TOOLKIT_GTK)
      8 #include <gtk/gtk.h>
      9 #elif defined(USE_X11)
     10 #include <cairo/cairo.h>
     11 #endif
     12 
     13 #include <algorithm>
     14 
     15 #include "base/auto_reset.h"
     16 #include "base/basictypes.h"
     17 #include "base/command_line.h"
     18 #include "base/file_util.h"
     19 #include "base/logging.h"
     20 #include "base/memory/ref_counted.h"
     21 #include "base/memory/scoped_ptr.h"
     22 #include "base/process/process.h"
     23 #include "base/strings/string_split.h"
     24 #include "base/strings/string_util.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "base/version.h"
     27 #include "content/child/child_process.h"
     28 #include "content/child/npapi/npobject_proxy.h"
     29 #include "content/child/npapi/npobject_stub.h"
     30 #include "content/child/npapi/npobject_util.h"
     31 #include "content/child/npapi/webplugin_resource_client.h"
     32 #include "content/child/plugin_messages.h"
     33 #include "content/common/content_constants_internal.h"
     34 #include "content/common/frame_messages.h"
     35 #include "content/common/view_messages.h"
     36 #include "content/public/renderer/content_renderer_client.h"
     37 #include "content/renderer/npapi/plugin_channel_host.h"
     38 #include "content/renderer/npapi/webplugin_impl.h"
     39 #include "content/renderer/render_thread_impl.h"
     40 #include "content/renderer/render_view_impl.h"
     41 #include "content/renderer/sad_plugin.h"
     42 #include "ipc/ipc_channel_handle.h"
     43 #include "net/base/mime_util.h"
     44 #include "skia/ext/platform_canvas.h"
     45 #include "third_party/WebKit/public/web/WebBindings.h"
     46 #include "third_party/WebKit/public/web/WebDocument.h"
     47 #include "third_party/WebKit/public/web/WebFrame.h"
     48 #include "third_party/WebKit/public/web/WebView.h"
     49 #include "third_party/WebKit/public/platform/WebDragData.h"
     50 #include "third_party/WebKit/public/platform/WebString.h"
     51 #include "ui/gfx/blit.h"
     52 #include "ui/gfx/canvas.h"
     53 #include "ui/gfx/native_widget_types.h"
     54 #include "ui/gfx/size.h"
     55 #include "ui/gfx/skia_util.h"
     56 #include "webkit/common/cursors/webcursor.h"
     57 
     58 #if defined(OS_POSIX)
     59 #include "ipc/ipc_channel_posix.h"
     60 #endif
     61 
     62 #if defined(OS_MACOSX)
     63 #include "base/mac/mac_util.h"
     64 #endif
     65 
     66 #if defined(OS_WIN)
     67 #include "content/public/common/sandbox_init.h"
     68 #endif
     69 
     70 using blink::WebBindings;
     71 using blink::WebCursorInfo;
     72 using blink::WebDragData;
     73 using blink::WebInputEvent;
     74 using blink::WebString;
     75 using blink::WebView;
     76 
     77 namespace content {
     78 
     79 namespace {
     80 
     81 class ScopedLogLevel {
     82  public:
     83   explicit ScopedLogLevel(int level);
     84   ~ScopedLogLevel();
     85 
     86  private:
     87   int old_level_;
     88 
     89   DISALLOW_COPY_AND_ASSIGN(ScopedLogLevel);
     90 };
     91 
     92 ScopedLogLevel::ScopedLogLevel(int level)
     93     : old_level_(logging::GetMinLogLevel()) {
     94   logging::SetMinLogLevel(level);
     95 }
     96 
     97 ScopedLogLevel::~ScopedLogLevel() {
     98   logging::SetMinLogLevel(old_level_);
     99 }
    100 
    101 // Proxy for WebPluginResourceClient.  The object owns itself after creation,
    102 // deleting itself after its callback has been called.
    103 class ResourceClientProxy : public WebPluginResourceClient {
    104  public:
    105   ResourceClientProxy(PluginChannelHost* channel, int instance_id)
    106     : channel_(channel), instance_id_(instance_id), resource_id_(0),
    107       multibyte_response_expected_(false) {
    108   }
    109 
    110   virtual ~ResourceClientProxy() {
    111   }
    112 
    113   void Initialize(unsigned long resource_id, const GURL& url, int notify_id) {
    114     resource_id_ = resource_id;
    115     channel_->Send(new PluginMsg_HandleURLRequestReply(
    116         instance_id_, resource_id, url, notify_id));
    117   }
    118 
    119   void InitializeForSeekableStream(unsigned long resource_id,
    120                                    int range_request_id) {
    121     resource_id_ = resource_id;
    122     multibyte_response_expected_ = true;
    123     channel_->Send(new PluginMsg_HTTPRangeRequestReply(
    124         instance_id_, resource_id, range_request_id));
    125   }
    126 
    127   // PluginResourceClient implementation:
    128   virtual void WillSendRequest(const GURL& url, int http_status_code) OVERRIDE {
    129     DCHECK(channel_.get() != NULL);
    130     channel_->Send(new PluginMsg_WillSendRequest(
    131         instance_id_, resource_id_, url, http_status_code));
    132   }
    133 
    134   virtual void DidReceiveResponse(const std::string& mime_type,
    135                                   const std::string& headers,
    136                                   uint32 expected_length,
    137                                   uint32 last_modified,
    138                                   bool request_is_seekable) OVERRIDE {
    139     DCHECK(channel_.get() != NULL);
    140     PluginMsg_DidReceiveResponseParams params;
    141     params.id = resource_id_;
    142     params.mime_type = mime_type;
    143     params.headers = headers;
    144     params.expected_length = expected_length;
    145     params.last_modified = last_modified;
    146     params.request_is_seekable = request_is_seekable;
    147     // Grab a reference on the underlying channel so it does not get
    148     // deleted from under us.
    149     scoped_refptr<PluginChannelHost> channel_ref(channel_);
    150     channel_->Send(new PluginMsg_DidReceiveResponse(instance_id_, params));
    151   }
    152 
    153   virtual void DidReceiveData(const char* buffer,
    154                               int length,
    155                               int data_offset) OVERRIDE {
    156     DCHECK(channel_.get() != NULL);
    157     DCHECK_GT(length, 0);
    158     std::vector<char> data;
    159     data.resize(static_cast<size_t>(length));
    160     memcpy(&data.front(), buffer, length);
    161     // Grab a reference on the underlying channel so it does not get
    162     // deleted from under us.
    163     scoped_refptr<PluginChannelHost> channel_ref(channel_);
    164     channel_->Send(new PluginMsg_DidReceiveData(instance_id_, resource_id_,
    165                                                 data, data_offset));
    166   }
    167 
    168   virtual void DidFinishLoading(unsigned long resource_id) OVERRIDE {
    169     DCHECK(channel_.get() != NULL);
    170     DCHECK_EQ(resource_id, resource_id_);
    171     channel_->Send(new PluginMsg_DidFinishLoading(instance_id_, resource_id_));
    172     channel_ = NULL;
    173     base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    174   }
    175 
    176   virtual void DidFail(unsigned long resource_id) OVERRIDE {
    177     DCHECK(channel_.get() != NULL);
    178     DCHECK_EQ(resource_id, resource_id_);
    179     channel_->Send(new PluginMsg_DidFail(instance_id_, resource_id_));
    180     channel_ = NULL;
    181     base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    182   }
    183 
    184   virtual bool IsMultiByteResponseExpected() OVERRIDE {
    185     return multibyte_response_expected_;
    186   }
    187 
    188   virtual int ResourceId() OVERRIDE {
    189     return resource_id_;
    190   }
    191 
    192  private:
    193   scoped_refptr<PluginChannelHost> channel_;
    194   int instance_id_;
    195   unsigned long resource_id_;
    196   // Set to true if the response expected is a multibyte response.
    197   // For e.g. response for a HTTP byte range request.
    198   bool multibyte_response_expected_;
    199 };
    200 
    201 }  // namespace
    202 
    203 WebPluginDelegateProxy::WebPluginDelegateProxy(
    204     WebPluginImpl* plugin,
    205     const std::string& mime_type,
    206     const base::WeakPtr<RenderViewImpl>& render_view,
    207     RenderFrameImpl* render_frame)
    208     : render_view_(render_view),
    209       render_frame_(render_frame),
    210       plugin_(plugin),
    211       uses_shared_bitmaps_(false),
    212 #if defined(OS_MACOSX)
    213       uses_compositor_(false),
    214 #elif defined(OS_WIN)
    215       dummy_activation_window_(NULL),
    216 #endif
    217       window_(gfx::kNullPluginWindow),
    218       mime_type_(mime_type),
    219       instance_id_(MSG_ROUTING_NONE),
    220       npobject_(NULL),
    221       npp_(new NPP_t),
    222       sad_plugin_(NULL),
    223       invalidate_pending_(false),
    224       transparent_(false),
    225       front_buffer_index_(0),
    226       page_url_(render_view_->webview()->mainFrame()->document().url()) {
    227 }
    228 
    229 WebPluginDelegateProxy::~WebPluginDelegateProxy() {
    230   if (npobject_)
    231     WebBindings::releaseObject(npobject_);
    232 }
    233 
    234 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {}
    235 
    236 WebPluginDelegateProxy::SharedBitmap::~SharedBitmap() {}
    237 
    238 void WebPluginDelegateProxy::PluginDestroyed() {
    239 #if defined(OS_MACOSX) || defined(OS_WIN)
    240   // Ensure that the renderer doesn't think the plugin still has focus.
    241   if (render_view_)
    242     render_view_->PluginFocusChanged(false, instance_id_);
    243 #endif
    244 
    245 #if defined(OS_WIN)
    246   if (dummy_activation_window_ && render_view_) {
    247     render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowDestroyed(
    248         render_view_->routing_id(), dummy_activation_window_));
    249   }
    250   dummy_activation_window_ = NULL;
    251 #endif
    252 
    253   if (window_)
    254     WillDestroyWindow();
    255 
    256   if (render_view_.get())
    257     render_view_->UnregisterPluginDelegate(this);
    258 
    259   if (channel_host_.get()) {
    260     Send(new PluginMsg_DestroyInstance(instance_id_));
    261 
    262     // Must remove the route after sending the destroy message, rather than
    263     // before, since RemoveRoute can lead to all the outstanding NPObjects
    264     // being told the channel went away if this was the last instance.
    265     channel_host_->RemoveRoute(instance_id_);
    266 
    267     // Remove the mapping between our instance-Id and NPP identifiers, used by
    268     // the channel to track object ownership, before releasing it.
    269     channel_host_->RemoveMappingForNPObjectOwner(instance_id_);
    270 
    271     // Release the channel host now. If we are is the last reference to the
    272     // channel, this avoids a race where this renderer asks a new connection to
    273     // the same plugin between now and the time 'this' is actually deleted.
    274     // Destroying the channel host is what releases the channel name -> FD
    275     // association on POSIX, and if we ask for a new connection before it is
    276     // released, the plugin will give us a new FD, and we'll assert when trying
    277     // to associate it with the channel name.
    278     channel_host_ = NULL;
    279   }
    280 
    281   plugin_ = NULL;
    282 
    283   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    284 }
    285 
    286 bool WebPluginDelegateProxy::Initialize(
    287     const GURL& url,
    288     const std::vector<std::string>& arg_names,
    289     const std::vector<std::string>& arg_values,
    290     bool load_manually) {
    291   // TODO(shess): Attempt to work around http://crbug.com/97285 and
    292   // http://crbug.com/141055 by retrying the connection.  Reports seem
    293   // to indicate that the plugin hasn't crashed, and that the problem
    294   // is not 100% persistent.
    295   const size_t kAttempts = 2;
    296 
    297   bool result = false;
    298   scoped_refptr<PluginChannelHost> channel_host;
    299   int instance_id = 0;
    300 
    301   for (size_t attempt = 0; !result && attempt < kAttempts; attempt++) {
    302 #if defined(OS_MACOSX)
    303     // TODO(shess): Debugging for http://crbug.com/97285 .  See comment
    304     // in plugin_channel_host.cc.
    305     scoped_ptr<base::AutoReset<bool> > track_nested_removes(
    306         new base::AutoReset<bool>(PluginChannelHost::GetRemoveTrackingFlag(),
    307                                   true));
    308 #endif
    309 
    310     IPC::ChannelHandle channel_handle;
    311     if (!RenderThreadImpl::current()->Send(new FrameHostMsg_OpenChannelToPlugin(
    312             render_frame_->GetRoutingID(), url, page_url_, mime_type_,
    313             &channel_handle, &info_))) {
    314       continue;
    315     }
    316 
    317     if (channel_handle.name.empty()) {
    318       // We got an invalid handle.  Either the plugin couldn't be found (which
    319       // shouldn't happen, since if we got here the plugin should exist) or the
    320       // plugin crashed on initialization.
    321       if (!info_.path.empty()) {
    322         render_view_->main_render_frame()->PluginCrashed(
    323             info_.path, base::kNullProcessId);
    324         LOG(ERROR) << "Plug-in crashed on start";
    325 
    326         // Return true so that the plugin widget is created and we can paint the
    327         // crashed plugin there.
    328         return true;
    329       }
    330       LOG(ERROR) << "Plug-in couldn't be found";
    331       return false;
    332     }
    333 
    334     channel_host =
    335         PluginChannelHost::GetPluginChannelHost(
    336             channel_handle, ChildProcess::current()->io_message_loop_proxy());
    337     if (!channel_host.get()) {
    338       LOG(ERROR) << "Couldn't get PluginChannelHost";
    339       continue;
    340     }
    341 #if defined(OS_MACOSX)
    342     track_nested_removes.reset();
    343 #endif
    344 
    345     {
    346       // TODO(bauerb): Debugging for http://crbug.com/141055.
    347       ScopedLogLevel log_level(-2);  // Equivalent to --v=2
    348       result = channel_host->Send(new PluginMsg_CreateInstance(
    349           mime_type_, &instance_id));
    350       if (!result) {
    351         LOG(ERROR) << "Couldn't send PluginMsg_CreateInstance";
    352         continue;
    353       }
    354     }
    355   }
    356 
    357   // Failed too often, give up.
    358   if (!result)
    359     return false;
    360 
    361   channel_host_ = channel_host;
    362   instance_id_ = instance_id;
    363 
    364   channel_host_->AddRoute(instance_id_, this, NULL);
    365 
    366   // Inform the channel of the mapping between our instance-Id and dummy NPP
    367   // identifier, for use in object ownership tracking.
    368   channel_host_->AddMappingForNPObjectOwner(instance_id_, GetPluginNPP());
    369 
    370   // Now tell the PluginInstance in the plugin process to initialize.
    371   PluginMsg_Init_Params params;
    372   params.url = url;
    373   params.page_url = page_url_;
    374   params.arg_names = arg_names;
    375   params.arg_values = arg_values;
    376   params.host_render_view_routing_id = render_view_->routing_id();
    377   params.load_manually = load_manually;
    378 
    379   result = false;
    380   Send(new PluginMsg_Init(instance_id_, params, &transparent_, &result));
    381 
    382   if (!result)
    383     LOG(WARNING) << "PluginMsg_Init returned false";
    384 
    385   render_view_->RegisterPluginDelegate(this);
    386 
    387   return result;
    388 }
    389 
    390 bool WebPluginDelegateProxy::Send(IPC::Message* msg) {
    391   if (!channel_host_.get()) {
    392     DLOG(WARNING) << "dropping message because channel host is null";
    393     delete msg;
    394     return false;
    395   }
    396 
    397   return channel_host_->Send(msg);
    398 }
    399 
    400 void WebPluginDelegateProxy::SendJavaScriptStream(const GURL& url,
    401                                                   const std::string& result,
    402                                                   bool success,
    403                                                   int notify_id) {
    404   Send(new PluginMsg_SendJavaScriptStream(
    405       instance_id_, url, result, success, notify_id));
    406 }
    407 
    408 void WebPluginDelegateProxy::DidReceiveManualResponse(
    409     const GURL& url, const std::string& mime_type,
    410     const std::string& headers, uint32 expected_length,
    411     uint32 last_modified) {
    412   PluginMsg_DidReceiveResponseParams params;
    413   params.id = 0;
    414   params.mime_type = mime_type;
    415   params.headers = headers;
    416   params.expected_length = expected_length;
    417   params.last_modified = last_modified;
    418   Send(new PluginMsg_DidReceiveManualResponse(instance_id_, url, params));
    419 }
    420 
    421 void WebPluginDelegateProxy::DidReceiveManualData(const char* buffer,
    422                                                   int length) {
    423   DCHECK_GT(length, 0);
    424   std::vector<char> data;
    425   data.resize(static_cast<size_t>(length));
    426   memcpy(&data.front(), buffer, length);
    427   Send(new PluginMsg_DidReceiveManualData(instance_id_, data));
    428 }
    429 
    430 void WebPluginDelegateProxy::DidFinishManualLoading() {
    431   Send(new PluginMsg_DidFinishManualLoading(instance_id_));
    432 }
    433 
    434 void WebPluginDelegateProxy::DidManualLoadFail() {
    435   Send(new PluginMsg_DidManualLoadFail(instance_id_));
    436 }
    437 
    438 bool WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
    439   GetContentClient()->SetActiveURL(page_url_);
    440 
    441   bool handled = true;
    442   IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateProxy, msg)
    443     IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindow, OnSetWindow)
    444     IPC_MESSAGE_HANDLER(PluginHostMsg_CancelResource, OnCancelResource)
    445     IPC_MESSAGE_HANDLER(PluginHostMsg_InvalidateRect, OnInvalidateRect)
    446     IPC_MESSAGE_HANDLER(PluginHostMsg_GetWindowScriptNPObject,
    447                         OnGetWindowScriptNPObject)
    448     IPC_MESSAGE_HANDLER(PluginHostMsg_GetPluginElement, OnGetPluginElement)
    449     IPC_MESSAGE_HANDLER(PluginHostMsg_ResolveProxy, OnResolveProxy)
    450     IPC_MESSAGE_HANDLER(PluginHostMsg_SetCookie, OnSetCookie)
    451     IPC_MESSAGE_HANDLER(PluginHostMsg_GetCookies, OnGetCookies)
    452     IPC_MESSAGE_HANDLER(PluginHostMsg_URLRequest, OnHandleURLRequest)
    453     IPC_MESSAGE_HANDLER(PluginHostMsg_CancelDocumentLoad, OnCancelDocumentLoad)
    454     IPC_MESSAGE_HANDLER(PluginHostMsg_InitiateHTTPRangeRequest,
    455                         OnInitiateHTTPRangeRequest)
    456     IPC_MESSAGE_HANDLER(PluginHostMsg_DidStartLoading, OnDidStartLoading)
    457     IPC_MESSAGE_HANDLER(PluginHostMsg_DidStopLoading, OnDidStopLoading)
    458     IPC_MESSAGE_HANDLER(PluginHostMsg_DeferResourceLoading,
    459                         OnDeferResourceLoading)
    460     IPC_MESSAGE_HANDLER(PluginHostMsg_URLRedirectResponse,
    461                         OnURLRedirectResponse)
    462     IPC_MESSAGE_HANDLER(PluginHostMsg_CheckIfRunInsecureContent,
    463                         OnCheckIfRunInsecureContent)
    464 #if defined(OS_WIN)
    465     IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindowlessData, OnSetWindowlessData)
    466     IPC_MESSAGE_HANDLER(PluginHostMsg_NotifyIMEStatus, OnNotifyIMEStatus)
    467 #endif
    468 #if defined(OS_MACOSX)
    469     IPC_MESSAGE_HANDLER(PluginHostMsg_FocusChanged,
    470                         OnFocusChanged);
    471     IPC_MESSAGE_HANDLER(PluginHostMsg_StartIme,
    472                         OnStartIme);
    473     IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginEnabledRendering,
    474                         OnAcceleratedPluginEnabledRendering)
    475     IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginAllocatedIOSurface,
    476                         OnAcceleratedPluginAllocatedIOSurface)
    477     IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginSwappedIOSurface,
    478                         OnAcceleratedPluginSwappedIOSurface)
    479 #endif
    480     IPC_MESSAGE_UNHANDLED(handled = false)
    481   IPC_END_MESSAGE_MAP()
    482   DCHECK(handled);
    483   return handled;
    484 }
    485 
    486 void WebPluginDelegateProxy::OnChannelError() {
    487   if (plugin_) {
    488     if (window_) {
    489       // The actual WebPluginDelegate never got a chance to tell the WebPlugin
    490       // its window was going away. Do it on its behalf.
    491       WillDestroyWindow();
    492     }
    493     plugin_->Invalidate();
    494   }
    495   if (!channel_host_->expecting_shutdown()) {
    496     render_view_->main_render_frame()->PluginCrashed(
    497         info_.path, channel_host_->peer_pid());
    498   }
    499 
    500 #if defined(OS_MACOSX) || defined(OS_WIN)
    501   // Ensure that the renderer doesn't think the plugin still has focus.
    502   if (render_view_)
    503     render_view_->PluginFocusChanged(false, instance_id_);
    504 #endif
    505 }
    506 
    507 static void CopyTransportDIBHandleForMessage(
    508     const TransportDIB::Handle& handle_in,
    509     TransportDIB::Handle* handle_out,
    510     base::ProcessId peer_pid) {
    511 #if defined(OS_MACOSX)
    512   // On Mac, TransportDIB::Handle is typedef'ed to FileDescriptor, and
    513   // FileDescriptor message fields needs to remain valid until the message is
    514   // sent or else the sendmsg() call will fail.
    515   if ((handle_out->fd = HANDLE_EINTR(dup(handle_in.fd))) < 0) {
    516     PLOG(ERROR) << "dup()";
    517     return;
    518   }
    519   handle_out->auto_close = true;
    520 #elif defined(OS_WIN)
    521   // On Windows we need to duplicate the handle for the plugin process.
    522   *handle_out = NULL;
    523   BrokerDuplicateHandle(handle_in, peer_pid, handle_out,
    524                         FILE_MAP_READ | FILE_MAP_WRITE, 0);
    525   DCHECK(*handle_out != NULL);
    526 #else
    527   // Don't need to do anything special for other platforms.
    528   *handle_out = handle_in;
    529 #endif
    530 }
    531 
    532 void WebPluginDelegateProxy::SendUpdateGeometry(
    533     bool bitmaps_changed) {
    534   PluginMsg_UpdateGeometry_Param param;
    535   param.window_rect = plugin_rect_;
    536   param.clip_rect = clip_rect_;
    537   param.windowless_buffer0 = TransportDIB::DefaultHandleValue();
    538   param.windowless_buffer1 = TransportDIB::DefaultHandleValue();
    539   param.windowless_buffer_index = back_buffer_index();
    540 
    541 #if defined(OS_POSIX)
    542   // If we're using POSIX mmap'd TransportDIBs, sending the handle across
    543   // IPC establishes a new mapping rather than just sending a window ID,
    544   // so only do so if we've actually changed the shared memory bitmaps.
    545   if (bitmaps_changed)
    546 #endif
    547   {
    548     if (transport_stores_[0].dib)
    549       CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(),
    550                                        &param.windowless_buffer0,
    551                                        channel_host_->peer_pid());
    552 
    553     if (transport_stores_[1].dib)
    554       CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(),
    555                                        &param.windowless_buffer1,
    556                                        channel_host_->peer_pid());
    557   }
    558 
    559   IPC::Message* msg;
    560 #if defined(OS_WIN)
    561   if (UseSynchronousGeometryUpdates()) {
    562     msg = new PluginMsg_UpdateGeometrySync(instance_id_, param);
    563   } else  // NOLINT
    564 #endif
    565   {
    566     msg = new PluginMsg_UpdateGeometry(instance_id_, param);
    567     msg->set_unblock(true);
    568   }
    569 
    570   Send(msg);
    571 }
    572 
    573 void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
    574                                             const gfx::Rect& clip_rect) {
    575   // window_rect becomes either a window in native windowing system
    576   // coords, or a backing buffer.  In either case things will go bad
    577   // if the rectangle is very large.
    578   if (window_rect.width() < 0  || window_rect.width() > kMaxPluginSideLength ||
    579       window_rect.height() < 0 || window_rect.height() > kMaxPluginSideLength ||
    580       // We know this won't overflow due to above checks.
    581       static_cast<uint32>(window_rect.width()) *
    582           static_cast<uint32>(window_rect.height()) > kMaxPluginSize) {
    583     return;
    584   }
    585 
    586   plugin_rect_ = window_rect;
    587   clip_rect_ = clip_rect;
    588 
    589   bool bitmaps_changed = false;
    590 
    591   if (uses_shared_bitmaps_) {
    592     if (!front_buffer_canvas() ||
    593         (window_rect.width() != front_buffer_canvas()->getDevice()->width() ||
    594          window_rect.height() != front_buffer_canvas()->getDevice()->height()))
    595     {
    596       bitmaps_changed = true;
    597 
    598       // Create a shared memory section that the plugin paints into
    599       // asynchronously.
    600       ResetWindowlessBitmaps();
    601       if (!window_rect.IsEmpty()) {
    602         if (!CreateSharedBitmap(&transport_stores_[0].dib,
    603                                 &transport_stores_[0].canvas) ||
    604             !CreateSharedBitmap(&transport_stores_[1].dib,
    605                                 &transport_stores_[1].canvas)) {
    606           DCHECK(false);
    607           ResetWindowlessBitmaps();
    608           return;
    609         }
    610       }
    611     }
    612   }
    613 
    614   SendUpdateGeometry(bitmaps_changed);
    615 }
    616 
    617 void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
    618   transport_stores_[0].dib.reset();
    619   transport_stores_[1].dib.reset();
    620 
    621   transport_stores_[0].canvas.reset();
    622   transport_stores_[1].canvas.reset();
    623   transport_store_painted_ = gfx::Rect();
    624   front_buffer_diff_ = gfx::Rect();
    625 }
    626 
    627 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) {
    628   const size_t stride =
    629       skia::PlatformCanvasStrideForWidth(plugin_rect.width());
    630   return stride * plugin_rect.height();
    631 }
    632 
    633 #if !defined(OS_WIN)
    634 bool WebPluginDelegateProxy::CreateLocalBitmap(
    635     std::vector<uint8>* memory,
    636     scoped_ptr<skia::PlatformCanvas>* canvas) {
    637   const size_t size = BitmapSizeForPluginRect(plugin_rect_);
    638   memory->resize(size);
    639   if (memory->size() != size)
    640     return false;
    641   canvas->reset(skia::CreatePlatformCanvas(
    642       plugin_rect_.width(), plugin_rect_.height(), true, &((*memory)[0]),
    643       skia::CRASH_ON_FAILURE));
    644   return true;
    645 }
    646 #endif
    647 
    648 bool WebPluginDelegateProxy::CreateSharedBitmap(
    649     scoped_ptr<TransportDIB>* memory,
    650     scoped_ptr<skia::PlatformCanvas>* canvas) {
    651   const size_t size = BitmapSizeForPluginRect(plugin_rect_);
    652 #if defined(OS_POSIX) && !defined(OS_MACOSX)
    653   memory->reset(TransportDIB::Create(size, 0));
    654   if (!memory->get())
    655     return false;
    656 #endif
    657 #if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
    658   TransportDIB::Handle handle;
    659   IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, false, &handle);
    660   if (!RenderThreadImpl::current()->Send(msg))
    661     return false;
    662   if (handle.fd < 0)
    663     return false;
    664   memory->reset(TransportDIB::Map(handle));
    665 #else
    666   static uint32 sequence_number = 0;
    667   memory->reset(TransportDIB::Create(size, sequence_number++));
    668 #endif
    669   canvas->reset((*memory)->GetPlatformCanvas(plugin_rect_.width(),
    670                                              plugin_rect_.height()));
    671   return !!canvas->get();
    672 }
    673 
    674 void WebPluginDelegateProxy::Paint(SkCanvas* canvas,
    675                                    const gfx::Rect& damaged_rect) {
    676   // Limit the damaged rectangle to whatever is contained inside the plugin
    677   // rectangle, as that's the rectangle that we'll actually draw.
    678   gfx::Rect rect = gfx::IntersectRects(damaged_rect, plugin_rect_);
    679 
    680   // If the plugin is no longer connected (channel crashed) draw a crashed
    681   // plugin bitmap
    682   if (!channel_host_.get() || !channel_host_->channel_valid()) {
    683     // Lazily load the sad plugin image.
    684     if (!sad_plugin_)
    685       sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
    686     if (sad_plugin_)
    687       PaintSadPlugin(canvas, plugin_rect_, *sad_plugin_);
    688     return;
    689   }
    690 
    691   if (!uses_shared_bitmaps_)
    692     return;
    693 
    694   // We got a paint before the plugin's coordinates, so there's no buffer to
    695   // copy from.
    696   if (!front_buffer_canvas())
    697     return;
    698 
    699   gfx::Rect offset_rect = rect;
    700   offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
    701 
    702   // transport_store_painted_ is really a bounding box, so in principle this
    703   // check could falsely indicate that we don't need to paint offset_rect, but
    704   // in practice it works fine.
    705   if (!transport_store_painted_.Contains(offset_rect)) {
    706     Send(new PluginMsg_Paint(instance_id_, offset_rect));
    707     // Since the plugin is not blocked on the renderer in this context, there is
    708     // a chance that it will begin repainting the back-buffer before we complete
    709     // capturing the data. Buffer flipping would increase that risk because
    710     // geometry update is asynchronous, so we don't want to use buffer flipping
    711     // here.
    712     UpdateFrontBuffer(offset_rect, false);
    713   }
    714 
    715   const SkBitmap& bitmap =
    716       front_buffer_canvas()->getDevice()->accessBitmap(false);
    717   SkPaint paint;
    718   paint.setXfermodeMode(
    719       transparent_ ? SkXfermode::kSrcATop_Mode : SkXfermode::kSrc_Mode);
    720   SkIRect src_rect = gfx::RectToSkIRect(offset_rect);
    721   canvas->drawBitmapRect(bitmap,
    722                          &src_rect,
    723                          gfx::RectToSkRect(rect),
    724                          &paint);
    725 
    726   if (invalidate_pending_) {
    727     // Only send the PaintAck message if this paint is in response to an
    728     // invalidate from the plugin, since this message acts as an access token
    729     // to ensure only one process is using the transport dib at a time.
    730     invalidate_pending_ = false;
    731     Send(new PluginMsg_DidPaint(instance_id_));
    732   }
    733 }
    734 
    735 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
    736   if (npobject_)
    737     return WebBindings::retainObject(npobject_);
    738 
    739   int route_id = MSG_ROUTING_NONE;
    740   Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
    741   if (route_id == MSG_ROUTING_NONE)
    742     return NULL;
    743 
    744   npobject_ = NPObjectProxy::Create(
    745       channel_host_.get(), route_id, 0, page_url_, GetPluginNPP());
    746 
    747   return WebBindings::retainObject(npobject_);
    748 }
    749 
    750 NPP WebPluginDelegateProxy::GetPluginNPP() {
    751   // Return a dummy NPP for WebKit to use to identify this plugin.
    752   return npp_.get();
    753 }
    754 
    755 bool WebPluginDelegateProxy::GetFormValue(base::string16* value) {
    756   bool success = false;
    757   Send(new PluginMsg_GetFormValue(instance_id_, value, &success));
    758   return success;
    759 }
    760 
    761 void WebPluginDelegateProxy::DidFinishLoadWithReason(
    762     const GURL& url, NPReason reason, int notify_id) {
    763   Send(new PluginMsg_DidFinishLoadWithReason(
    764       instance_id_, url, reason, notify_id));
    765 }
    766 
    767 void WebPluginDelegateProxy::SetFocus(bool focused) {
    768   Send(new PluginMsg_SetFocus(instance_id_, focused));
    769 #if defined(OS_WIN)
    770   if (render_view_)
    771     render_view_->PluginFocusChanged(focused, instance_id_);
    772 #endif
    773 }
    774 
    775 bool WebPluginDelegateProxy::HandleInputEvent(
    776     const WebInputEvent& event,
    777     WebCursor::CursorInfo* cursor_info) {
    778   bool handled;
    779   WebCursor cursor;
    780   // A windowless plugin can enter a modal loop in the context of a
    781   // NPP_HandleEvent call, in which case we need to pump messages to
    782   // the plugin. We pass of the corresponding event handle to the
    783   // plugin process, which is set if the plugin does enter a modal loop.
    784   IPC::SyncMessage* message = new PluginMsg_HandleInputEvent(
    785       instance_id_, &event, &handled, &cursor);
    786   message->set_pump_messages_event(modal_loop_pump_messages_event_.get());
    787   Send(message);
    788   return handled;
    789 }
    790 
    791 int WebPluginDelegateProxy::GetProcessId() {
    792   return channel_host_->peer_pid();
    793 }
    794 
    795 void WebPluginDelegateProxy::SetContentAreaFocus(bool has_focus) {
    796   IPC::Message* msg = new PluginMsg_SetContentAreaFocus(instance_id_,
    797                                                         has_focus);
    798   // Make sure focus events are delivered in the right order relative to
    799   // sync messages they might interact with (Paint, HandleEvent, etc.).
    800   msg->set_unblock(true);
    801   Send(msg);
    802 }
    803 
    804 #if defined(OS_WIN)
    805 void WebPluginDelegateProxy::ImeCompositionUpdated(
    806     const base::string16& text,
    807     const std::vector<int>& clauses,
    808     const std::vector<int>& target,
    809     int cursor_position,
    810     int plugin_id) {
    811   // Dispatch the raw IME data if this plug-in is the focused one.
    812   if (instance_id_ != plugin_id)
    813     return;
    814 
    815   IPC::Message* msg = new PluginMsg_ImeCompositionUpdated(instance_id_,
    816       text, clauses, target, cursor_position);
    817   msg->set_unblock(true);
    818   Send(msg);
    819 }
    820 
    821 void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
    822                                                      int plugin_id) {
    823   // Dispatch the IME text if this plug-in is the focused one.
    824   if (instance_id_ != plugin_id)
    825     return;
    826 
    827   IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_, text);
    828   msg->set_unblock(true);
    829   Send(msg);
    830 }
    831 #endif
    832 
    833 #if defined(OS_MACOSX)
    834 void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) {
    835   IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_,
    836                                                    window_has_focus);
    837   // Make sure focus events are delivered in the right order relative to
    838   // sync messages they might interact with (Paint, HandleEvent, etc.).
    839   msg->set_unblock(true);
    840   Send(msg);
    841 }
    842 
    843 void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) {
    844   IPC::Message* msg;
    845   if (is_visible) {
    846     gfx::Rect window_frame = render_view_->rootWindowRect();
    847     gfx::Rect view_frame = render_view_->windowRect();
    848     blink::WebView* webview = render_view_->webview();
    849     msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame,
    850                                        webview && webview->isActive());
    851   } else {
    852     msg = new PluginMsg_ContainerHidden(instance_id_);
    853   }
    854   // Make sure visibility events are delivered in the right order relative to
    855   // sync messages they might interact with (Paint, HandleEvent, etc.).
    856   msg->set_unblock(true);
    857   Send(msg);
    858 }
    859 
    860 void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame,
    861                                                 gfx::Rect view_frame) {
    862   IPC::Message* msg = new PluginMsg_WindowFrameChanged(instance_id_,
    863                                                        window_frame,
    864                                                        view_frame);
    865   // Make sure frame events are delivered in the right order relative to
    866   // sync messages they might interact with (e.g., HandleEvent).
    867   msg->set_unblock(true);
    868   Send(msg);
    869 }
    870 void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
    871                                                      int plugin_id) {
    872   // If the message isn't intended for this plugin, there's nothing to do.
    873   if (instance_id_ != plugin_id)
    874     return;
    875 
    876   IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_,
    877                                                             text);
    878   // Order relative to other key events is important.
    879   msg->set_unblock(true);
    880   Send(msg);
    881 }
    882 #endif  // OS_MACOSX
    883 
    884 void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
    885 #if defined(OS_MACOSX)
    886   uses_shared_bitmaps_ = !window && !uses_compositor_;
    887 #else
    888   uses_shared_bitmaps_ = !window;
    889 #endif
    890   window_ = window;
    891   if (plugin_)
    892     plugin_->SetWindow(window);
    893 }
    894 
    895 void WebPluginDelegateProxy::WillDestroyWindow() {
    896   DCHECK(window_);
    897   plugin_->WillDestroyWindow(window_);
    898   window_ = gfx::kNullPluginWindow;
    899 }
    900 
    901 #if defined(OS_WIN)
    902 void WebPluginDelegateProxy::OnSetWindowlessData(
    903       HANDLE modal_loop_pump_messages_event,
    904       gfx::NativeViewId dummy_activation_window) {
    905   DCHECK(modal_loop_pump_messages_event_ == NULL);
    906   DCHECK(dummy_activation_window_ == NULL);
    907 
    908   dummy_activation_window_ = dummy_activation_window;
    909   render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowCreated(
    910       render_view_->routing_id(), dummy_activation_window_));
    911 
    912   // Bug 25583: this can be null because some "virus scanners" block the
    913   // DuplicateHandle call in the plugin process.
    914   if (!modal_loop_pump_messages_event)
    915     return;
    916 
    917   modal_loop_pump_messages_event_.reset(
    918       new base::WaitableEvent(modal_loop_pump_messages_event));
    919 }
    920 
    921 void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
    922                                                const gfx::Rect& caret_rect) {
    923   if (!render_view_)
    924     return;
    925 
    926   render_view_->Send(new ViewHostMsg_TextInputTypeChanged(
    927       render_view_->routing_id(),
    928       static_cast<ui::TextInputType>(input_type),
    929       ui::TEXT_INPUT_MODE_DEFAULT,
    930       true));
    931 
    932   ViewHostMsg_SelectionBounds_Params bounds_params;
    933   bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect;
    934   bounds_params.anchor_dir = bounds_params.focus_dir =
    935       blink::WebTextDirectionLeftToRight;
    936   bounds_params.is_anchor_first = true;
    937   render_view_->Send(new ViewHostMsg_SelectionBoundsChanged(
    938       render_view_->routing_id(),
    939       bounds_params));
    940 }
    941 #endif
    942 
    943 void WebPluginDelegateProxy::OnCancelResource(int id) {
    944   if (plugin_)
    945     plugin_->CancelResource(id);
    946 }
    947 
    948 void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
    949   if (!plugin_)
    950     return;
    951 
    952   // Clip the invalidation rect to the plugin bounds; the plugin may have been
    953   // resized since the invalidate message was sent.
    954   gfx::Rect clipped_rect =
    955       gfx::IntersectRects(rect, gfx::Rect(plugin_rect_.size()));
    956 
    957   invalidate_pending_ = true;
    958   // The plugin is blocked on the renderer because the invalidate message it has
    959   // sent us is synchronous, so we can use buffer flipping here if the caller
    960   // allows it.
    961   UpdateFrontBuffer(clipped_rect, true);
    962   plugin_->InvalidateRect(clipped_rect);
    963 }
    964 
    965 void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
    966     int route_id, bool* success) {
    967   *success = false;
    968   NPObject* npobject = NULL;
    969   if (plugin_)
    970     npobject = plugin_->GetWindowScriptNPObject();
    971 
    972   if (!npobject)
    973     return;
    974 
    975   // The stub will delete itself when the proxy tells it that it's released, or
    976   // otherwise when the channel is closed.
    977   new NPObjectStub(npobject, channel_host_.get(), route_id, 0, page_url_);
    978   *success = true;
    979 }
    980 
    981 void WebPluginDelegateProxy::OnResolveProxy(const GURL& url,
    982                                             bool* result,
    983                                             std::string* proxy_list) {
    984   *result = RenderThreadImpl::current()->ResolveProxy(url, proxy_list);
    985 }
    986 
    987 void WebPluginDelegateProxy::OnGetPluginElement(int route_id, bool* success) {
    988   *success = false;
    989   NPObject* npobject = NULL;
    990   if (plugin_)
    991     npobject = plugin_->GetPluginElement();
    992   if (!npobject)
    993     return;
    994 
    995   // The stub will delete itself when the proxy tells it that it's released, or
    996   // otherwise when the channel is closed.
    997   new NPObjectStub(
    998       npobject, channel_host_.get(), route_id, 0, page_url_);
    999   *success = true;
   1000 }
   1001 
   1002 void WebPluginDelegateProxy::OnSetCookie(const GURL& url,
   1003                                          const GURL& first_party_for_cookies,
   1004                                          const std::string& cookie) {
   1005   if (plugin_)
   1006     plugin_->SetCookie(url, first_party_for_cookies, cookie);
   1007 }
   1008 
   1009 void WebPluginDelegateProxy::OnGetCookies(const GURL& url,
   1010                                           const GURL& first_party_for_cookies,
   1011                                           std::string* cookies) {
   1012   DCHECK(cookies);
   1013   if (plugin_)
   1014     *cookies = plugin_->GetCookies(url, first_party_for_cookies);
   1015 }
   1016 
   1017 void WebPluginDelegateProxy::CopyFromBackBufferToFrontBuffer(
   1018     const gfx::Rect& rect) {
   1019 #if defined(OS_MACOSX)
   1020   // Blitting the bits directly is much faster than going through CG, and since
   1021   // the goal is just to move the raw pixels between two bitmaps with the same
   1022   // pixel format (no compositing, color correction, etc.), it's safe.
   1023   const size_t stride =
   1024       skia::PlatformCanvasStrideForWidth(plugin_rect_.width());
   1025   const size_t chunk_size = 4 * rect.width();
   1026   DCHECK(back_buffer_dib() != NULL);
   1027   uint8* source_data = static_cast<uint8*>(back_buffer_dib()->memory()) +
   1028                        rect.y() * stride + 4 * rect.x();
   1029   DCHECK(front_buffer_dib() != NULL);
   1030   uint8* target_data = static_cast<uint8*>(front_buffer_dib()->memory()) +
   1031                        rect.y() * stride + 4 * rect.x();
   1032   for (int row = 0; row < rect.height(); ++row) {
   1033     memcpy(target_data, source_data, chunk_size);
   1034     source_data += stride;
   1035     target_data += stride;
   1036   }
   1037 #else
   1038   BlitCanvasToCanvas(front_buffer_canvas(),
   1039                      rect,
   1040                      back_buffer_canvas(),
   1041                      rect.origin());
   1042 #endif
   1043 }
   1044 
   1045 void WebPluginDelegateProxy::UpdateFrontBuffer(
   1046     const gfx::Rect& rect,
   1047     bool allow_buffer_flipping) {
   1048   if (!front_buffer_canvas()) {
   1049     return;
   1050   }
   1051 
   1052 #if defined(OS_WIN)
   1053   // If SendUpdateGeometry() would block on the plugin process then we don't
   1054   // want to use buffer flipping at all since it would add extra locking.
   1055   // (Alternatively we could probably safely use async updates for buffer
   1056   // flipping all the time since the size is not changing.)
   1057   if (UseSynchronousGeometryUpdates()) {
   1058     allow_buffer_flipping = false;
   1059   }
   1060 #endif
   1061 
   1062   // Plugin has just painted "rect" into the back-buffer, so the front-buffer
   1063   // no longer holds the latest content for that rectangle.
   1064   front_buffer_diff_.Subtract(rect);
   1065   if (allow_buffer_flipping && front_buffer_diff_.IsEmpty()) {
   1066     // Back-buffer contains the latest content for all areas; simply flip
   1067     // the buffers.
   1068     front_buffer_index_ = back_buffer_index();
   1069     SendUpdateGeometry(false);
   1070     // The front-buffer now holds newer content for this region than the
   1071     // back-buffer.
   1072     front_buffer_diff_ = rect;
   1073   } else {
   1074     // Back-buffer contains the latest content for "rect" but the front-buffer
   1075     // contains the latest content for some other areas (or buffer flipping not
   1076     // allowed); fall back to copying the data.
   1077     CopyFromBackBufferToFrontBuffer(rect);
   1078   }
   1079   transport_store_painted_.Union(rect);
   1080 }
   1081 
   1082 void WebPluginDelegateProxy::OnHandleURLRequest(
   1083     const PluginHostMsg_URLRequest_Params& params) {
   1084   const char* data = NULL;
   1085   if (params.buffer.size())
   1086     data = &params.buffer[0];
   1087 
   1088   const char* target = NULL;
   1089   if (params.target.length())
   1090     target = params.target.c_str();
   1091 
   1092   plugin_->HandleURLRequest(
   1093       params.url.c_str(), params.method.c_str(), target, data,
   1094       static_cast<unsigned int>(params.buffer.size()), params.notify_id,
   1095       params.popups_allowed, params.notify_redirects);
   1096 }
   1097 
   1098 WebPluginResourceClient* WebPluginDelegateProxy::CreateResourceClient(
   1099     unsigned long resource_id, const GURL& url, int notify_id) {
   1100   if (!channel_host_.get())
   1101     return NULL;
   1102 
   1103   ResourceClientProxy* proxy =
   1104       new ResourceClientProxy(channel_host_.get(), instance_id_);
   1105   proxy->Initialize(resource_id, url, notify_id);
   1106   return proxy;
   1107 }
   1108 
   1109 WebPluginResourceClient* WebPluginDelegateProxy::CreateSeekableResourceClient(
   1110     unsigned long resource_id, int range_request_id) {
   1111   if (!channel_host_.get())
   1112     return NULL;
   1113 
   1114   ResourceClientProxy* proxy =
   1115       new ResourceClientProxy(channel_host_.get(), instance_id_);
   1116   proxy->InitializeForSeekableStream(resource_id, range_request_id);
   1117   return proxy;
   1118 }
   1119 
   1120 void WebPluginDelegateProxy::FetchURL(unsigned long resource_id,
   1121                                       int notify_id,
   1122                                       const GURL& url,
   1123                                       const GURL& first_party_for_cookies,
   1124                                       const std::string& method,
   1125                                       const char* buf,
   1126                                       unsigned int len,
   1127                                       const GURL& referrer,
   1128                                       bool notify_redirects,
   1129                                       bool is_plugin_src_load,
   1130                                       int origin_pid,
   1131                                       int render_view_id) {
   1132   PluginMsg_FetchURL_Params params;
   1133   params.resource_id = resource_id;
   1134   params.notify_id = notify_id;
   1135   params.url = url;
   1136   params.first_party_for_cookies = first_party_for_cookies;
   1137   params.method = method;
   1138   if (len) {
   1139     params.post_data.resize(len);
   1140     memcpy(&params.post_data.front(), buf, len);
   1141   }
   1142   params.referrer = referrer;
   1143   params.notify_redirect = notify_redirects;
   1144   params.is_plugin_src_load = is_plugin_src_load;
   1145   params.render_view_id = render_view_id;
   1146   Send(new PluginMsg_FetchURL(instance_id_, params));
   1147 }
   1148 
   1149 #if defined(OS_MACOSX)
   1150 void WebPluginDelegateProxy::OnFocusChanged(bool focused) {
   1151   if (render_view_)
   1152     render_view_->PluginFocusChanged(focused, instance_id_);
   1153 }
   1154 
   1155 void WebPluginDelegateProxy::OnStartIme() {
   1156   if (render_view_)
   1157     render_view_->StartPluginIme();
   1158 }
   1159 #endif
   1160 
   1161 gfx::PluginWindowHandle WebPluginDelegateProxy::GetPluginWindowHandle() {
   1162   return window_;
   1163 }
   1164 
   1165 void WebPluginDelegateProxy::OnCancelDocumentLoad() {
   1166   plugin_->CancelDocumentLoad();
   1167 }
   1168 
   1169 void WebPluginDelegateProxy::OnInitiateHTTPRangeRequest(
   1170     const std::string& url,
   1171     const std::string& range_info,
   1172     int range_request_id) {
   1173   plugin_->InitiateHTTPRangeRequest(
   1174       url.c_str(), range_info.c_str(), range_request_id);
   1175 }
   1176 
   1177 void WebPluginDelegateProxy::OnDidStartLoading() {
   1178   plugin_->DidStartLoading();
   1179 }
   1180 
   1181 void WebPluginDelegateProxy::OnDidStopLoading() {
   1182   plugin_->DidStopLoading();
   1183 }
   1184 
   1185 void WebPluginDelegateProxy::OnDeferResourceLoading(unsigned long resource_id,
   1186                                                     bool defer) {
   1187   plugin_->SetDeferResourceLoading(resource_id, defer);
   1188 }
   1189 
   1190 #if defined(OS_MACOSX)
   1191 void WebPluginDelegateProxy::OnAcceleratedPluginEnabledRendering() {
   1192   uses_compositor_ = true;
   1193   OnSetWindow(gfx::kNullPluginWindow);
   1194 }
   1195 
   1196 void WebPluginDelegateProxy::OnAcceleratedPluginAllocatedIOSurface(
   1197     int32 width,
   1198     int32 height,
   1199     uint32 surface_id) {
   1200   if (plugin_)
   1201     plugin_->AcceleratedPluginAllocatedIOSurface(width, height, surface_id);
   1202 }
   1203 
   1204 void WebPluginDelegateProxy::OnAcceleratedPluginSwappedIOSurface() {
   1205   if (plugin_)
   1206     plugin_->AcceleratedPluginSwappedIOSurface();
   1207 }
   1208 #endif
   1209 
   1210 #if defined(OS_WIN)
   1211 bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() {
   1212   // Need to update geometry synchronously with WMP, otherwise if a site
   1213   // scripts the plugin to start playing while it's in the middle of handling
   1214   // an update geometry message, videos don't play.  See urls in bug 20260.
   1215   if (info_.name.find(ASCIIToUTF16("Windows Media Player")) !=
   1216       base::string16::npos)
   1217     return true;
   1218 
   1219   // The move networks plugin needs to be informed of geometry updates
   1220   // synchronously.
   1221   std::vector<WebPluginMimeType>::iterator index;
   1222   for (index = info_.mime_types.begin(); index != info_.mime_types.end();
   1223        index++) {
   1224     if (index->mime_type == "application/x-vnd.moveplayer.qm" ||
   1225         index->mime_type == "application/x-vnd.moveplay2.qm" ||
   1226         index->mime_type == "application/x-vnd.movenetworks.qm" ||
   1227         index->mime_type == "application/x-vnd.mnplayer.qm") {
   1228       return true;
   1229     }
   1230   }
   1231   return false;
   1232 }
   1233 #endif
   1234 
   1235 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow,
   1236                                                    int resource_id) {
   1237   if (!plugin_)
   1238     return;
   1239 
   1240   plugin_->URLRedirectResponse(allow, resource_id);
   1241 }
   1242 
   1243 void WebPluginDelegateProxy::OnCheckIfRunInsecureContent(const GURL& url,
   1244                                                          bool* result) {
   1245   *result = plugin_->CheckIfRunInsecureContent(url);
   1246 }
   1247 
   1248 }  // namespace content
   1249