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