Home | History | Annotate | Download | only in 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/plugin/webplugin_proxy.h"
      6 
      7 #include "build/build_config.h"
      8 
      9 #include "base/bind.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/memory/scoped_handle.h"
     12 #include "base/memory/shared_memory.h"
     13 #include "build/build_config.h"
     14 #include "content/child/npapi/npobject_proxy.h"
     15 #include "content/child/npapi/npobject_util.h"
     16 #include "content/child/npapi/webplugin_delegate_impl.h"
     17 #include "content/child/npapi/webplugin_resource_client.h"
     18 #include "content/child/plugin_messages.h"
     19 #include "content/plugin/plugin_channel.h"
     20 #include "content/plugin/plugin_thread.h"
     21 #include "content/public/common/content_client.h"
     22 #include "content/public/common/url_constants.h"
     23 #include "skia/ext/platform_canvas.h"
     24 #include "skia/ext/platform_device.h"
     25 #include "third_party/WebKit/public/web/WebBindings.h"
     26 #include "ui/gfx/blit.h"
     27 #include "ui/gfx/canvas.h"
     28 
     29 #if defined(OS_MACOSX)
     30 #include "base/mac/mac_util.h"
     31 #include "base/mac/scoped_cftyperef.h"
     32 #include "content/plugin/webplugin_accelerated_surface_proxy_mac.h"
     33 #endif
     34 
     35 #if defined(USE_X11)
     36 #include "ui/base/x/x11_util_internal.h"
     37 #endif
     38 
     39 #if defined(OS_WIN)
     40 #include "content/common/plugin_process_messages.h"
     41 #include "content/public/common/sandbox_init.h"
     42 #endif
     43 
     44 using blink::WebBindings;
     45 
     46 namespace content {
     47 
     48 WebPluginProxy::SharedTransportDIB::SharedTransportDIB(TransportDIB* dib)
     49     : dib_(dib) {
     50 }
     51 
     52 WebPluginProxy::SharedTransportDIB::~SharedTransportDIB() {
     53 }
     54 
     55 WebPluginProxy::WebPluginProxy(
     56     PluginChannel* channel,
     57     int route_id,
     58     const GURL& page_url,
     59     int host_render_view_routing_id)
     60     : channel_(channel),
     61       route_id_(route_id),
     62       window_npobject_(NULL),
     63       plugin_element_(NULL),
     64       delegate_(NULL),
     65       waiting_for_paint_(false),
     66       page_url_(page_url),
     67       windowless_buffer_index_(0),
     68       host_render_view_routing_id_(host_render_view_routing_id),
     69       weak_factory_(this) {
     70 #if defined(USE_X11)
     71   windowless_shm_pixmaps_[0] = None;
     72   windowless_shm_pixmaps_[1] = None;
     73   use_shm_pixmap_ = false;
     74 
     75   // If the X server supports SHM pixmaps
     76   // and the color depth and masks match,
     77   // then consider using SHM pixmaps for windowless plugin painting.
     78   XDisplay* display = gfx::GetXDisplay();
     79   if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP &&
     80       gfx::BitsPerPixelForPixmapDepth(
     81           display, DefaultDepth(display, DefaultScreen(display))) == 32) {
     82     Visual* vis = DefaultVisual(display, DefaultScreen(display));
     83 
     84     if (vis->red_mask == 0xff0000 &&
     85         vis->green_mask == 0xff00 &&
     86         vis->blue_mask == 0xff)
     87       use_shm_pixmap_ = true;
     88   }
     89 #endif
     90 }
     91 
     92 WebPluginProxy::~WebPluginProxy() {
     93 #if defined(USE_X11)
     94   if (windowless_shm_pixmaps_[0] != None)
     95     XFreePixmap(gfx::GetXDisplay(), windowless_shm_pixmaps_[0]);
     96   if (windowless_shm_pixmaps_[1] != None)
     97     XFreePixmap(gfx::GetXDisplay(), windowless_shm_pixmaps_[1]);
     98 #endif
     99 
    100 #if defined(OS_MACOSX)
    101   // Destroy the surface early, since it may send messages during cleanup.
    102   if (accelerated_surface_)
    103     accelerated_surface_.reset();
    104 #endif
    105 
    106   if (plugin_element_)
    107     WebBindings::releaseObject(plugin_element_);
    108   if (window_npobject_)
    109     WebBindings::releaseObject(window_npobject_);
    110 }
    111 
    112 bool WebPluginProxy::Send(IPC::Message* msg) {
    113   return channel_->Send(msg);
    114 }
    115 
    116 void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) {
    117   Send(new PluginHostMsg_SetWindow(route_id_, window));
    118 }
    119 
    120 void WebPluginProxy::SetAcceptsInputEvents(bool accepts) {
    121   NOTREACHED();
    122 }
    123 
    124 void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) {
    125 #if defined(OS_WIN)
    126   PluginThread::current()->Send(
    127       new PluginProcessHostMsg_PluginWindowDestroyed(
    128           window, ::GetParent(window)));
    129 #elif defined(USE_X11)
    130   // Nothing to do.
    131 #else
    132   NOTIMPLEMENTED();
    133 #endif
    134 }
    135 
    136 #if defined(OS_WIN)
    137 void WebPluginProxy::SetWindowlessData(
    138     HANDLE pump_messages_event, gfx::NativeViewId dummy_activation_window) {
    139   HANDLE pump_messages_event_for_renderer = NULL;
    140   BrokerDuplicateHandle(pump_messages_event, channel_->peer_pid(),
    141                                  &pump_messages_event_for_renderer,
    142                                  SYNCHRONIZE | EVENT_MODIFY_STATE, 0);
    143   DCHECK(pump_messages_event_for_renderer);
    144   Send(new PluginHostMsg_SetWindowlessData(
    145       route_id_, pump_messages_event_for_renderer, dummy_activation_window));
    146 }
    147 #endif
    148 
    149 void WebPluginProxy::CancelResource(unsigned long id) {
    150   Send(new PluginHostMsg_CancelResource(route_id_, id));
    151   resource_clients_.erase(id);
    152 }
    153 
    154 void WebPluginProxy::Invalidate() {
    155   gfx::Rect rect(0, 0,
    156                  delegate_->GetRect().width(),
    157                  delegate_->GetRect().height());
    158   InvalidateRect(rect);
    159 }
    160 
    161 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
    162 #if defined(OS_MACOSX)
    163   // If this is a Core Animation plugin, all we need to do is inform the
    164   // delegate.
    165   if (!windowless_context()) {
    166     delegate_->PluginDidInvalidate();
    167     return;
    168   }
    169 
    170   // Some plugins will send invalidates larger than their own rect when
    171   // offscreen, so constrain invalidates to the plugin rect.
    172   gfx::Rect plugin_rect = delegate_->GetRect();
    173   plugin_rect.set_origin(gfx::Point(0, 0));
    174   plugin_rect.Intersect(rect);
    175   const gfx::Rect invalidate_rect(plugin_rect);
    176 #else
    177   const gfx::Rect invalidate_rect(rect);
    178 #endif
    179   damaged_rect_.Union(invalidate_rect);
    180   // Ignore NPN_InvalidateRect calls with empty rects.  Also don't send an
    181   // invalidate if it's outside the clipping region, since if we did it won't
    182   // lead to a paint and we'll be stuck waiting forever for a DidPaint response.
    183   //
    184   // TODO(piman): There is a race condition here, because this test assumes
    185   // that when the paint actually occurs, the clip rect will not have changed.
    186   // This is not true because scrolling (or window resize) could occur and be
    187   // handled by the renderer before it receives the InvalidateRect message,
    188   // changing the clip rect and then not painting.
    189   if (damaged_rect_.IsEmpty() ||
    190       !delegate_->GetClipRect().Intersects(damaged_rect_))
    191     return;
    192 
    193   // Only send a single InvalidateRect message at a time.  From DidPaint we
    194   // will dispatch an additional InvalidateRect message if necessary.
    195   if (!waiting_for_paint_) {
    196     waiting_for_paint_ = true;
    197     // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn
    198     // need to be painted asynchronously as per the NPAPI spec.
    199     base::MessageLoop::current()->PostTask(
    200         FROM_HERE,
    201         base::Bind(&WebPluginProxy::OnPaint,
    202                    weak_factory_.GetWeakPtr(),
    203                    damaged_rect_));
    204     damaged_rect_ = gfx::Rect();
    205   }
    206 }
    207 
    208 NPObject* WebPluginProxy::GetWindowScriptNPObject() {
    209   if (window_npobject_)
    210     return window_npobject_;
    211 
    212   int npobject_route_id = channel_->GenerateRouteID();
    213   bool success = false;
    214   Send(new PluginHostMsg_GetWindowScriptNPObject(
    215       route_id_, npobject_route_id, &success));
    216   if (!success)
    217     return NULL;
    218 
    219   // PluginChannel creates a dummy owner identifier for unknown owners, so
    220   // use that.
    221   NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
    222 
    223   window_npobject_ = NPObjectProxy::Create(channel_.get(),
    224                                            npobject_route_id,
    225                                            host_render_view_routing_id_,
    226                                            page_url_,
    227                                            owner);
    228 
    229   return window_npobject_;
    230 }
    231 
    232 NPObject* WebPluginProxy::GetPluginElement() {
    233   if (plugin_element_)
    234     return plugin_element_;
    235 
    236   int npobject_route_id = channel_->GenerateRouteID();
    237   bool success = false;
    238   Send(new PluginHostMsg_GetPluginElement(route_id_, npobject_route_id,
    239                                           &success));
    240   if (!success)
    241     return NULL;
    242 
    243   // PluginChannel creates a dummy owner identifier for unknown owners, so
    244   // use that.
    245   NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
    246 
    247   plugin_element_ = NPObjectProxy::Create(channel_.get(),
    248                                           npobject_route_id,
    249                                           host_render_view_routing_id_,
    250                                           page_url_,
    251                                           owner);
    252 
    253   return plugin_element_;
    254 }
    255 
    256 bool WebPluginProxy::FindProxyForUrl(const GURL& url, std::string* proxy_list) {
    257   bool result = false;
    258   Send(new PluginHostMsg_ResolveProxy(route_id_, url, &result, proxy_list));
    259   return result;
    260 }
    261 
    262 void WebPluginProxy::SetCookie(const GURL& url,
    263                                const GURL& first_party_for_cookies,
    264                                const std::string& cookie) {
    265   Send(new PluginHostMsg_SetCookie(route_id_, url,
    266                                    first_party_for_cookies, cookie));
    267 }
    268 
    269 std::string WebPluginProxy::GetCookies(const GURL& url,
    270                                        const GURL& first_party_for_cookies) {
    271   std::string cookies;
    272   Send(new PluginHostMsg_GetCookies(route_id_, url,
    273                                     first_party_for_cookies, &cookies));
    274 
    275   return cookies;
    276 }
    277 
    278 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) {
    279   ResourceClientMap::iterator iterator = resource_clients_.find(id);
    280   // The IPC messages which deal with streams are now asynchronous. It is
    281   // now possible to receive stream messages from the renderer for streams
    282   // which may have been cancelled by the plugin.
    283   if (iterator == resource_clients_.end()) {
    284     return NULL;
    285   }
    286 
    287   return iterator->second;
    288 }
    289 
    290 int WebPluginProxy::GetRendererId() {
    291   if (channel_.get())
    292     return channel_->renderer_id();
    293   return -1;
    294 }
    295 
    296 void WebPluginProxy::DidPaint() {
    297   // If we have an accumulated damaged rect, then check to see if we need to
    298   // send out another InvalidateRect message.
    299   waiting_for_paint_ = false;
    300   if (!damaged_rect_.IsEmpty())
    301     InvalidateRect(damaged_rect_);
    302 }
    303 
    304 void WebPluginProxy::OnResourceCreated(int resource_id,
    305                                        WebPluginResourceClient* client) {
    306   DCHECK(resource_clients_.find(resource_id) == resource_clients_.end());
    307   resource_clients_[resource_id] = client;
    308 }
    309 
    310 void WebPluginProxy::HandleURLRequest(const char* url,
    311                                       const char* method,
    312                                       const char* target,
    313                                       const char* buf,
    314                                       unsigned int len,
    315                                       int notify_id,
    316                                       bool popups_allowed,
    317                                       bool notify_redirects) {
    318  if (!target && (0 == base::strcasecmp(method, "GET"))) {
    319     // Please refer to https://bugzilla.mozilla.org/show_bug.cgi?id=366082
    320     // for more details on this.
    321     if (delegate_->GetQuirks() &
    322         WebPluginDelegateImpl::PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS) {
    323       GURL request_url(url);
    324       if (!request_url.SchemeIs(kHttpScheme) &&
    325           !request_url.SchemeIs(kHttpsScheme) &&
    326           !request_url.SchemeIs(kFtpScheme)) {
    327         return;
    328       }
    329     }
    330   }
    331 
    332   PluginHostMsg_URLRequest_Params params;
    333   params.url = url;
    334   params.method = method;
    335   if (target)
    336     params.target = std::string(target);
    337 
    338   if (len) {
    339     params.buffer.resize(len);
    340     memcpy(&params.buffer.front(), buf, len);
    341   }
    342 
    343   params.notify_id = notify_id;
    344   params.popups_allowed = popups_allowed;
    345   params.notify_redirects = notify_redirects;
    346 
    347   Send(new PluginHostMsg_URLRequest(route_id_, params));
    348 }
    349 
    350 void WebPluginProxy::Paint(const gfx::Rect& rect) {
    351 #if defined(OS_MACOSX)
    352   if (!windowless_context())
    353     return;
    354 #else
    355   if (!windowless_canvas() || !windowless_canvas()->getDevice())
    356     return;
    357 #endif
    358 
    359   // Clear the damaged area so that if the plugin doesn't paint there we won't
    360   // end up with the old values.
    361   gfx::Rect offset_rect = rect;
    362   offset_rect.Offset(delegate_->GetRect().OffsetFromOrigin());
    363 #if defined(OS_MACOSX)
    364   CGContextSaveGState(windowless_context());
    365   // It is possible for windowless_contexts_ to change during plugin painting
    366   // (since the plugin can make a synchronous call during paint event handling),
    367   // in which case we don't want to try to restore later. Not an owning ref
    368   // since owning the ref without owning the shared backing memory doesn't make
    369   // sense, so this should only be used for pointer comparisons.
    370   CGContextRef saved_context_weak = windowless_context();
    371   // We also save the buffer index for the comparison because if we flip buffers
    372   // but haven't reallocated them then we do need to restore the context because
    373   // it is going to continue to be used.
    374   int saved_index = windowless_buffer_index_;
    375 
    376   CGContextClipToRect(windowless_context(), rect.ToCGRect());
    377   // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia
    378   // port to share code with the Darwin / CG port. All ports will eventually use
    379   // the common code below.
    380   delegate_->CGPaint(windowless_context(), rect);
    381   if (windowless_contexts_[saved_index].get() == saved_context_weak)
    382     CGContextRestoreGState(windowless_contexts_[saved_index]);
    383 #else
    384   // See above comment about windowless_context_ changing.
    385   // http::/crbug.com/139462
    386   skia::RefPtr<skia::PlatformCanvas> saved_canvas = windowless_canvas();
    387 #if defined(USE_X11)
    388   scoped_refptr<SharedTransportDIB> local_dib_ref(
    389       windowless_dibs_[windowless_buffer_index_]);
    390 #endif
    391 
    392   saved_canvas->save();
    393 
    394   // The given clip rect is relative to the plugin coordinate system.
    395   SkRect sk_rect = { SkIntToScalar(rect.x()),
    396                      SkIntToScalar(rect.y()),
    397                      SkIntToScalar(rect.right()),
    398                      SkIntToScalar(rect.bottom()) };
    399   saved_canvas->clipRect(sk_rect);
    400 
    401   // Fill a transparent value so that if the plugin supports transparency that
    402   // will work.
    403   saved_canvas->drawColor(SkColorSetARGB(0, 0, 0, 0), SkXfermode::kSrc_Mode);
    404 
    405   // Bring the windowless canvas into the window coordinate system, which is
    406   // how the plugin expects to draw (since the windowless API was originally
    407   // designed just for scribbling over the web page).
    408   saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()),
    409                           SkIntToScalar(-delegate_->GetRect().y()));
    410 
    411   // Before we send the invalidate, paint so that renderer uses the updated
    412   // bitmap.
    413   delegate_->Paint(saved_canvas.get(), offset_rect);
    414 
    415   saved_canvas->restore();
    416 #endif
    417 }
    418 
    419 void WebPluginProxy::UpdateGeometry(
    420     const gfx::Rect& window_rect,
    421     const gfx::Rect& clip_rect,
    422     const TransportDIB::Handle& windowless_buffer0,
    423     const TransportDIB::Handle& windowless_buffer1,
    424     int windowless_buffer_index) {
    425   gfx::Rect old = delegate_->GetRect();
    426   gfx::Rect old_clip_rect = delegate_->GetClipRect();
    427 
    428   // Update the buffers before doing anything that could call into plugin code,
    429   // so that we don't process buffer changes out of order if plugins make
    430   // synchronous calls that lead to nested UpdateGeometry calls.
    431   if (TransportDIB::is_valid_handle(windowless_buffer0)) {
    432     // The plugin's rect changed, so now we have new buffers to draw into.
    433     SetWindowlessBuffers(windowless_buffer0,
    434                          windowless_buffer1,
    435                          window_rect);
    436   }
    437 
    438   DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1);
    439   windowless_buffer_index_ = windowless_buffer_index;
    440 #if defined(USE_X11)
    441   delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap());
    442 #endif
    443 
    444 #if defined(OS_MACOSX)
    445   delegate_->UpdateGeometryAndContext(
    446       window_rect, clip_rect, windowless_context());
    447 #else
    448   delegate_->UpdateGeometry(window_rect, clip_rect);
    449 #endif
    450 
    451   // Send over any pending invalidates which occured when the plugin was
    452   // off screen.
    453   if (delegate_->IsWindowless() && !clip_rect.IsEmpty() &&
    454       !damaged_rect_.IsEmpty()) {
    455     InvalidateRect(damaged_rect_);
    456   }
    457 }
    458 
    459 #if defined(OS_WIN)
    460 
    461 void WebPluginProxy::CreateCanvasFromHandle(
    462     const TransportDIB::Handle& dib_handle,
    463     const gfx::Rect& window_rect,
    464     skia::RefPtr<skia::PlatformCanvas>* canvas) {
    465   *canvas = skia::AdoptRef(
    466       skia::CreatePlatformCanvas(window_rect.width(),
    467                                  window_rect.height(),
    468                                  true,
    469                                  dib_handle,
    470                                  skia::RETURN_NULL_ON_FAILURE));
    471   // The canvas does not own the section so we need to close it now.
    472   CloseHandle(dib_handle);
    473 }
    474 
    475 void WebPluginProxy::SetWindowlessBuffers(
    476     const TransportDIB::Handle& windowless_buffer0,
    477     const TransportDIB::Handle& windowless_buffer1,
    478     const gfx::Rect& window_rect) {
    479   CreateCanvasFromHandle(windowless_buffer0,
    480                          window_rect,
    481                          &windowless_canvases_[0]);
    482   if (!windowless_canvases_[0]) {
    483     windowless_canvases_[1].clear();
    484     return;
    485   }
    486   CreateCanvasFromHandle(windowless_buffer1,
    487                          window_rect,
    488                          &windowless_canvases_[1]);
    489   if (!windowless_canvases_[1]) {
    490     windowless_canvases_[0].clear();
    491     return;
    492   }
    493 }
    494 
    495 #elif defined(OS_MACOSX)
    496 
    497 void WebPluginProxy::CreateDIBAndCGContextFromHandle(
    498     const TransportDIB::Handle& dib_handle,
    499     const gfx::Rect& window_rect,
    500     scoped_ptr<TransportDIB>* dib_out,
    501     base::ScopedCFTypeRef<CGContextRef>* cg_context_out) {
    502   // Convert the shared memory handle to a handle that works in our process,
    503   // and then use that to create a CGContextRef.
    504   TransportDIB* dib = TransportDIB::Map(dib_handle);
    505   CGContextRef cg_context = NULL;
    506   if (dib) {
    507     cg_context = CGBitmapContextCreate(
    508         dib->memory(),
    509         window_rect.width(),
    510         window_rect.height(),
    511         8,
    512         4 * window_rect.width(),
    513         base::mac::GetSystemColorSpace(),
    514         kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
    515     CGContextTranslateCTM(cg_context, 0, window_rect.height());
    516     CGContextScaleCTM(cg_context, 1, -1);
    517   }
    518   dib_out->reset(dib);
    519   cg_context_out->reset(cg_context);
    520 }
    521 
    522 void WebPluginProxy::SetWindowlessBuffers(
    523     const TransportDIB::Handle& windowless_buffer0,
    524     const TransportDIB::Handle& windowless_buffer1,
    525     const gfx::Rect& window_rect) {
    526   CreateDIBAndCGContextFromHandle(windowless_buffer0,
    527                                   window_rect,
    528                                   &windowless_dibs_[0],
    529                                   &windowless_contexts_[0]);
    530   CreateDIBAndCGContextFromHandle(windowless_buffer1,
    531                                   window_rect,
    532                                   &windowless_dibs_[1],
    533                                   &windowless_contexts_[1]);
    534 }
    535 
    536 #elif defined(TOOLKIT_GTK)
    537 
    538 void WebPluginProxy::CreateDIBAndCanvasFromHandle(
    539     const TransportDIB::Handle& dib_handle,
    540     const gfx::Rect& window_rect,
    541     scoped_refptr<SharedTransportDIB>* dib_out,
    542     skia::RefPtr<skia::PlatformCanvas>* canvas) {
    543   TransportDIB* dib = TransportDIB::Map(dib_handle);
    544   // dib may be NULL if the renderer has already destroyed the TransportDIB by
    545   // the time we receive the handle, e.g. in case of multiple resizes.
    546   if (dib) {
    547     *canvas = skia::AdoptRef(
    548         dib->GetPlatformCanvas(window_rect.width(), window_rect.height()));
    549   } else {
    550     canvas->clear();
    551   }
    552   *dib_out = new SharedTransportDIB(dib);
    553 }
    554 
    555 void WebPluginProxy::CreateShmPixmapFromDIB(
    556     TransportDIB* dib,
    557     const gfx::Rect& window_rect,
    558     XID* pixmap_out) {
    559   if (dib) {
    560     XDisplay* display = gfx::GetXDisplay();
    561     XID root_window = ui::GetX11RootWindow();
    562     XShmSegmentInfo shminfo = {0};
    563 
    564     if (*pixmap_out != None)
    565       XFreePixmap(display, *pixmap_out);
    566 
    567     shminfo.shmseg = dib->MapToX(display);
    568     // Create a shared memory pixmap based on the image buffer.
    569     *pixmap_out = XShmCreatePixmap(display, root_window,
    570                                    NULL, &shminfo,
    571                                    window_rect.width(), window_rect.height(),
    572                                    DefaultDepth(display,
    573                                                 DefaultScreen(display)));
    574   }
    575 }
    576 
    577 void WebPluginProxy::SetWindowlessBuffers(
    578     const TransportDIB::Handle& windowless_buffer0,
    579     const TransportDIB::Handle& windowless_buffer1,
    580     const gfx::Rect& window_rect) {
    581   CreateDIBAndCanvasFromHandle(windowless_buffer0,
    582                                window_rect,
    583                                &windowless_dibs_[0],
    584                                &windowless_canvases_[0]);
    585   CreateDIBAndCanvasFromHandle(windowless_buffer1,
    586                                window_rect,
    587                                &windowless_dibs_[1],
    588                                &windowless_canvases_[1]);
    589 
    590   // If SHM pixmaps support is available, create SHM pixmaps to pass to the
    591   // delegate for windowless plugin painting.
    592   if (delegate_->IsWindowless() && use_shm_pixmap_) {
    593     CreateShmPixmapFromDIB(windowless_dibs_[0]->dib(),
    594                            window_rect,
    595                            &windowless_shm_pixmaps_[0]);
    596     CreateShmPixmapFromDIB(windowless_dibs_[1]->dib(),
    597                            window_rect,
    598                            &windowless_shm_pixmaps_[1]);
    599   }
    600 }
    601 
    602 #else
    603 
    604 void WebPluginProxy::SetWindowlessBuffers(
    605     const TransportDIB::Handle& windowless_buffer0,
    606     const TransportDIB::Handle& windowless_buffer1,
    607     const gfx::Rect& window_rect) {
    608   NOTIMPLEMENTED();
    609 }
    610 
    611 #endif
    612 
    613 void WebPluginProxy::CancelDocumentLoad() {
    614   Send(new PluginHostMsg_CancelDocumentLoad(route_id_));
    615 }
    616 
    617 void WebPluginProxy::InitiateHTTPRangeRequest(
    618     const char* url, const char* range_info, int range_request_id) {
    619   Send(new PluginHostMsg_InitiateHTTPRangeRequest(
    620       route_id_, url, range_info, range_request_id));
    621 }
    622 
    623 void WebPluginProxy::DidStartLoading() {
    624   Send(new PluginHostMsg_DidStartLoading(route_id_));
    625 }
    626 
    627 void WebPluginProxy::DidStopLoading() {
    628   Send(new PluginHostMsg_DidStopLoading(route_id_));
    629 }
    630 
    631 void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id,
    632                                              bool defer) {
    633   Send(new PluginHostMsg_DeferResourceLoading(route_id_, resource_id, defer));
    634 }
    635 
    636 #if defined(OS_MACOSX)
    637 void WebPluginProxy::FocusChanged(bool focused) {
    638   IPC::Message* msg = new PluginHostMsg_FocusChanged(route_id_, focused);
    639   Send(msg);
    640 }
    641 
    642 void WebPluginProxy::StartIme() {
    643   IPC::Message* msg = new PluginHostMsg_StartIme(route_id_);
    644   // This message can be sent during event-handling, and needs to be delivered
    645   // within that context.
    646   msg->set_unblock(true);
    647   Send(msg);
    648 }
    649 
    650 WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface(
    651     gfx::GpuPreference gpu_preference) {
    652   if (!accelerated_surface_)
    653     accelerated_surface_.reset(
    654         WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference));
    655   return accelerated_surface_.get();
    656 }
    657 
    658 void WebPluginProxy::AcceleratedPluginEnabledRendering() {
    659   Send(new PluginHostMsg_AcceleratedPluginEnabledRendering(route_id_));
    660 }
    661 
    662 void WebPluginProxy::AcceleratedPluginAllocatedIOSurface(int32 width,
    663                                                          int32 height,
    664                                                          uint32 surface_id) {
    665   Send(new PluginHostMsg_AcceleratedPluginAllocatedIOSurface(
    666       route_id_, width, height, surface_id));
    667 }
    668 
    669 void WebPluginProxy::AcceleratedPluginSwappedIOSurface() {
    670   Send(new PluginHostMsg_AcceleratedPluginSwappedIOSurface(
    671       route_id_));
    672 }
    673 #endif
    674 
    675 void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) {
    676   GetContentClient()->SetActiveURL(page_url_);
    677 
    678   Paint(damaged_rect);
    679   Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect));
    680 }
    681 
    682 bool WebPluginProxy::IsOffTheRecord() {
    683   return channel_->incognito();
    684 }
    685 
    686 void WebPluginProxy::ResourceClientDeleted(
    687     WebPluginResourceClient* resource_client) {
    688   // resource_client->ResourceId() is 0 at this point, so can't use it as an
    689   // index into the map.
    690   ResourceClientMap::iterator index = resource_clients_.begin();
    691   while (index != resource_clients_.end()) {
    692     WebPluginResourceClient* client = (*index).second;
    693     if (client == resource_client) {
    694       resource_clients_.erase(index);
    695       return;
    696     } else {
    697       index++;
    698     }
    699   }
    700 }
    701 
    702 void WebPluginProxy::URLRedirectResponse(bool allow, int resource_id) {
    703   Send(new PluginHostMsg_URLRedirectResponse(route_id_, allow, resource_id));
    704 }
    705 
    706 bool WebPluginProxy::CheckIfRunInsecureContent(const GURL& url) {
    707   bool result = true;
    708   Send(new PluginHostMsg_CheckIfRunInsecureContent(
    709       host_render_view_routing_id_, url, &result));
    710   return result;
    711 }
    712 
    713 #if defined(OS_WIN) && !defined(USE_AURA)
    714 void WebPluginProxy::UpdateIMEStatus() {
    715   // Retrieve the IME status from a plug-in and send it to a renderer process
    716   // when the plug-in has updated it.
    717   int input_type;
    718   gfx::Rect caret_rect;
    719   if (!delegate_->GetIMEStatus(&input_type, &caret_rect))
    720     return;
    721 
    722   Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect));
    723 }
    724 #endif
    725 
    726 }  // namespace content
    727