| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "chrome/plugin/webplugin_proxy.h" | |
| 6 | |
| 7 #include "build/build_config.h" | |
| 8 | |
| 9 #include "base/lazy_instance.h" | |
| 10 #include "base/scoped_handle.h" | |
| 11 #include "base/shared_memory.h" | |
| 12 #include "build/build_config.h" | |
| 13 #include "chrome/plugin/npobject_proxy.h" | |
| 14 #include "chrome/plugin/npobject_util.h" | |
| 15 #include "chrome/plugin/plugin_channel.h" | |
| 16 #include "chrome/plugin/plugin_thread.h" | |
| 17 #include "content/common/content_client.h" | |
| 18 #include "content/common/plugin_messages.h" | |
| 19 #include "skia/ext/platform_device.h" | |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | |
| 21 #include "ui/gfx/blit.h" | |
| 22 #include "ui/gfx/canvas.h" | |
| 23 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" | |
| 24 | |
| 25 #if defined(OS_MACOSX) | |
| 26 #include "base/mac/mac_util.h" | |
| 27 #include "base/mac/scoped_cftyperef.h" | |
| 28 #include "chrome/plugin/webplugin_accelerated_surface_proxy_mac.h" | |
| 29 #endif | |
| 30 | |
| 31 #if defined(OS_WIN) | |
| 32 #include "content/common/section_util_win.h" | |
| 33 #include "ui/gfx/gdi_util.h" | |
| 34 #endif | |
| 35 | |
| 36 #if defined(USE_X11) | |
| 37 #include "ui/base/x/x11_util_internal.h" | |
| 38 #endif | |
| 39 | |
| 40 using WebKit::WebBindings; | |
| 41 | |
| 42 using webkit::npapi::WebPluginResourceClient; | |
| 43 #if defined(OS_MACOSX) | |
| 44 using webkit::npapi::WebPluginAcceleratedSurface; | |
| 45 #endif | |
| 46 | |
| 47 WebPluginProxy::WebPluginProxy( | |
| 48 PluginChannel* channel, | |
| 49 int route_id, | |
| 50 const GURL& page_url, | |
| 51 gfx::NativeViewId containing_window, | |
| 52 int host_render_view_routing_id) | |
| 53 : channel_(channel), | |
| 54 route_id_(route_id), | |
| 55 window_npobject_(NULL), | |
| 56 plugin_element_(NULL), | |
| 57 delegate_(NULL), | |
| 58 waiting_for_paint_(false), | |
| 59 containing_window_(containing_window), | |
| 60 page_url_(page_url), | |
| 61 transparent_(false), | |
| 62 host_render_view_routing_id_(host_render_view_routing_id), | |
| 63 ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)) { | |
| 64 #if defined(USE_X11) | |
| 65 windowless_shm_pixmap_ = None; | |
| 66 use_shm_pixmap_ = false; | |
| 67 | |
| 68 // If the X server supports SHM pixmaps | |
| 69 // and the color depth and masks match, | |
| 70 // then consider using SHM pixmaps for windowless plugin painting. | |
| 71 Display* display = ui::GetXDisplay(); | |
| 72 if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP && | |
| 73 ui::BitsPerPixelForPixmapDepth( | |
| 74 display, DefaultDepth(display, 0)) == 32) { | |
| 75 Visual* vis = DefaultVisual(display, 0); | |
| 76 | |
| 77 if (vis->red_mask == 0xff0000 && | |
| 78 vis->green_mask == 0xff00 && | |
| 79 vis->blue_mask == 0xff) | |
| 80 use_shm_pixmap_ = true; | |
| 81 } | |
| 82 #endif | |
| 83 } | |
| 84 | |
| 85 WebPluginProxy::~WebPluginProxy() { | |
| 86 #if defined(USE_X11) | |
| 87 if (windowless_shm_pixmap_ != None) | |
| 88 XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmap_); | |
| 89 #endif | |
| 90 | |
| 91 #if defined(OS_MACOSX) | |
| 92 // Destroy the surface early, since it may send messages during cleanup. | |
| 93 if (accelerated_surface_.get()) | |
| 94 accelerated_surface_.reset(); | |
| 95 #endif | |
| 96 } | |
| 97 | |
| 98 bool WebPluginProxy::Send(IPC::Message* msg) { | |
| 99 return channel_->Send(msg); | |
| 100 } | |
| 101 | |
| 102 void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) { | |
| 103 Send(new PluginHostMsg_SetWindow(route_id_, window)); | |
| 104 } | |
| 105 | |
| 106 void WebPluginProxy::SetAcceptsInputEvents(bool accepts) { | |
| 107 NOTREACHED(); | |
| 108 } | |
| 109 | |
| 110 void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) { | |
| 111 #if defined(OS_WIN) | |
| 112 PluginThread::current()->Send( | |
| 113 new PluginProcessHostMsg_PluginWindowDestroyed( | |
| 114 window, ::GetParent(window))); | |
| 115 #elif defined(USE_X11) | |
| 116 // Nothing to do. | |
| 117 #else | |
| 118 NOTIMPLEMENTED(); | |
| 119 #endif | |
| 120 } | |
| 121 | |
| 122 #if defined(OS_WIN) | |
| 123 void WebPluginProxy::SetWindowlessPumpEvent(HANDLE pump_messages_event) { | |
| 124 HANDLE pump_messages_event_for_renderer = NULL; | |
| 125 DuplicateHandle(GetCurrentProcess(), pump_messages_event, | |
| 126 channel_->renderer_handle(), | |
| 127 &pump_messages_event_for_renderer, | |
| 128 0, FALSE, DUPLICATE_SAME_ACCESS); | |
| 129 DCHECK(pump_messages_event_for_renderer != NULL); | |
| 130 Send(new PluginHostMsg_SetWindowlessPumpEvent( | |
| 131 route_id_, pump_messages_event_for_renderer)); | |
| 132 } | |
| 133 #endif | |
| 134 | |
| 135 void WebPluginProxy::CancelResource(unsigned long id) { | |
| 136 Send(new PluginHostMsg_CancelResource(route_id_, id)); | |
| 137 resource_clients_.erase(id); | |
| 138 } | |
| 139 | |
| 140 void WebPluginProxy::Invalidate() { | |
| 141 gfx::Rect rect(0, 0, | |
| 142 delegate_->GetRect().width(), | |
| 143 delegate_->GetRect().height()); | |
| 144 InvalidateRect(rect); | |
| 145 } | |
| 146 | |
| 147 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { | |
| 148 #if defined(OS_MACOSX) | |
| 149 // If this is a Core Animation plugin, all we need to do is inform the | |
| 150 // delegate. | |
| 151 if (!windowless_context_.get()) { | |
| 152 delegate_->PluginDidInvalidate(); | |
| 153 return; | |
| 154 } | |
| 155 | |
| 156 // Some plugins will send invalidates larger than their own rect when | |
| 157 // offscreen, so constrain invalidates to the plugin rect. | |
| 158 gfx::Rect plugin_rect = delegate_->GetRect(); | |
| 159 plugin_rect.set_origin(gfx::Point(0, 0)); | |
| 160 const gfx::Rect invalidate_rect(rect.Intersect(plugin_rect)); | |
| 161 #else | |
| 162 const gfx::Rect invalidate_rect(rect); | |
| 163 #endif | |
| 164 damaged_rect_ = damaged_rect_.Union(invalidate_rect); | |
| 165 // Ignore NPN_InvalidateRect calls with empty rects. Also don't send an | |
| 166 // invalidate if it's outside the clipping region, since if we did it won't | |
| 167 // lead to a paint and we'll be stuck waiting forever for a DidPaint response. | |
| 168 // | |
| 169 // TODO(piman): There is a race condition here, because this test assumes | |
| 170 // that when the paint actually occurs, the clip rect will not have changed. | |
| 171 // This is not true because scrolling (or window resize) could occur and be | |
| 172 // handled by the renderer before it receives the InvalidateRect message, | |
| 173 // changing the clip rect and then not painting. | |
| 174 if (damaged_rect_.IsEmpty() || | |
| 175 !delegate_->GetClipRect().Intersects(damaged_rect_)) | |
| 176 return; | |
| 177 | |
| 178 // Only send a single InvalidateRect message at a time. From DidPaint we | |
| 179 // will dispatch an additional InvalidateRect message if necessary. | |
| 180 if (!waiting_for_paint_) { | |
| 181 waiting_for_paint_ = true; | |
| 182 // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn | |
| 183 // need to be painted asynchronously as per the NPAPI spec. | |
| 184 MessageLoop::current()->PostTask(FROM_HERE, | |
| 185 runnable_method_factory_.NewRunnableMethod( | |
| 186 &WebPluginProxy::OnPaint, damaged_rect_)); | |
| 187 damaged_rect_ = gfx::Rect(); | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 NPObject* WebPluginProxy::GetWindowScriptNPObject() { | |
| 192 if (window_npobject_) | |
| 193 return WebBindings::retainObject(window_npobject_); | |
| 194 | |
| 195 int npobject_route_id = channel_->GenerateRouteID(); | |
| 196 bool success = false; | |
| 197 Send(new PluginHostMsg_GetWindowScriptNPObject( | |
| 198 route_id_, npobject_route_id, &success)); | |
| 199 if (!success) | |
| 200 return NULL; | |
| 201 | |
| 202 window_npobject_ = NPObjectProxy::Create( | |
| 203 channel_, npobject_route_id, containing_window_, page_url_); | |
| 204 | |
| 205 return window_npobject_; | |
| 206 } | |
| 207 | |
| 208 NPObject* WebPluginProxy::GetPluginElement() { | |
| 209 if (plugin_element_) | |
| 210 return WebBindings::retainObject(plugin_element_); | |
| 211 | |
| 212 int npobject_route_id = channel_->GenerateRouteID(); | |
| 213 bool success = false; | |
| 214 Send(new PluginHostMsg_GetPluginElement(route_id_, npobject_route_id, | |
| 215 &success)); | |
| 216 if (!success) | |
| 217 return NULL; | |
| 218 | |
| 219 plugin_element_ = NPObjectProxy::Create( | |
| 220 channel_, npobject_route_id, containing_window_, page_url_); | |
| 221 | |
| 222 return plugin_element_; | |
| 223 } | |
| 224 | |
| 225 void WebPluginProxy::SetCookie(const GURL& url, | |
| 226 const GURL& first_party_for_cookies, | |
| 227 const std::string& cookie) { | |
| 228 Send(new PluginHostMsg_SetCookie(route_id_, url, | |
| 229 first_party_for_cookies, cookie)); | |
| 230 } | |
| 231 | |
| 232 std::string WebPluginProxy::GetCookies(const GURL& url, | |
| 233 const GURL& first_party_for_cookies) { | |
| 234 std::string cookies; | |
| 235 Send(new PluginHostMsg_GetCookies(route_id_, url, | |
| 236 first_party_for_cookies, &cookies)); | |
| 237 | |
| 238 return cookies; | |
| 239 } | |
| 240 | |
| 241 void WebPluginProxy::OnMissingPluginStatus(int status) { | |
| 242 Send(new PluginHostMsg_MissingPluginStatus(route_id_, status)); | |
| 243 } | |
| 244 | |
| 245 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) { | |
| 246 ResourceClientMap::iterator iterator = resource_clients_.find(id); | |
| 247 // The IPC messages which deal with streams are now asynchronous. It is | |
| 248 // now possible to receive stream messages from the renderer for streams | |
| 249 // which may have been cancelled by the plugin. | |
| 250 if (iterator == resource_clients_.end()) { | |
| 251 return NULL; | |
| 252 } | |
| 253 | |
| 254 return iterator->second; | |
| 255 } | |
| 256 | |
| 257 int WebPluginProxy::GetRendererId() { | |
| 258 if (channel_.get()) | |
| 259 return channel_->renderer_id(); | |
| 260 return -1; | |
| 261 } | |
| 262 | |
| 263 void WebPluginProxy::DidPaint() { | |
| 264 // If we have an accumulated damaged rect, then check to see if we need to | |
| 265 // send out another InvalidateRect message. | |
| 266 waiting_for_paint_ = false; | |
| 267 if (!damaged_rect_.IsEmpty()) | |
| 268 InvalidateRect(damaged_rect_); | |
| 269 } | |
| 270 | |
| 271 void WebPluginProxy::OnResourceCreated(int resource_id, | |
| 272 WebPluginResourceClient* client) { | |
| 273 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end()); | |
| 274 resource_clients_[resource_id] = client; | |
| 275 } | |
| 276 | |
| 277 void WebPluginProxy::HandleURLRequest(const char* url, | |
| 278 const char* method, | |
| 279 const char* target, | |
| 280 const char* buf, | |
| 281 unsigned int len, | |
| 282 int notify_id, | |
| 283 bool popups_allowed, | |
| 284 bool notify_redirects) { | |
| 285 if (!target && (0 == base::strcasecmp(method, "GET"))) { | |
| 286 // Please refer to https://bugzilla.mozilla.org/show_bug.cgi?id=366082 | |
| 287 // for more details on this. | |
| 288 if (delegate_->GetQuirks() & | |
| 289 webkit::npapi::WebPluginDelegateImpl:: | |
| 290 PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS) { | |
| 291 GURL request_url(url); | |
| 292 if (!request_url.SchemeIs("http") && | |
| 293 !request_url.SchemeIs("https") && | |
| 294 !request_url.SchemeIs("ftp")) { | |
| 295 return; | |
| 296 } | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 PluginHostMsg_URLRequest_Params params; | |
| 301 params.url = url; | |
| 302 params.method = method; | |
| 303 if (target) | |
| 304 params.target = std::string(target); | |
| 305 | |
| 306 if (len) { | |
| 307 params.buffer.resize(len); | |
| 308 memcpy(¶ms.buffer.front(), buf, len); | |
| 309 } | |
| 310 | |
| 311 params.notify_id = notify_id; | |
| 312 params.popups_allowed = popups_allowed; | |
| 313 params.notify_redirects = notify_redirects; | |
| 314 | |
| 315 Send(new PluginHostMsg_URLRequest(route_id_, params)); | |
| 316 } | |
| 317 | |
| 318 void WebPluginProxy::Paint(const gfx::Rect& rect) { | |
| 319 #if defined(OS_MACOSX) | |
| 320 if (!windowless_context_.get()) | |
| 321 return; | |
| 322 #else | |
| 323 if (!windowless_canvas_.get()) | |
| 324 return; | |
| 325 #endif | |
| 326 | |
| 327 // Clear the damaged area so that if the plugin doesn't paint there we won't | |
| 328 // end up with the old values. | |
| 329 gfx::Rect offset_rect = rect; | |
| 330 offset_rect.Offset(delegate_->GetRect().origin()); | |
| 331 #if defined(OS_MACOSX) | |
| 332 CGContextSaveGState(windowless_context_); | |
| 333 // It is possible for windowless_context_ to change during plugin painting | |
| 334 // (since the plugin can make a synchronous call during paint event handling), | |
| 335 // in which case we don't want to try to restore it later. Not an owning ref | |
| 336 // since owning the ref without owning the shared backing memory doesn't make | |
| 337 // sense, so this should only be used for pointer comparisons. | |
| 338 CGContextRef saved_context_weak = windowless_context_.get(); | |
| 339 | |
| 340 if (background_context_.get()) { | |
| 341 base::mac::ScopedCFTypeRef<CGImageRef> image( | |
| 342 CGBitmapContextCreateImage(background_context_)); | |
| 343 CGRect source_rect = rect.ToCGRect(); | |
| 344 // Flip the rect we use to pull from the canvas, since it's upside-down. | |
| 345 source_rect.origin.y = CGImageGetHeight(image) - rect.y() - rect.height(); | |
| 346 base::mac::ScopedCFTypeRef<CGImageRef> sub_image( | |
| 347 CGImageCreateWithImageInRect(image, source_rect)); | |
| 348 CGContextDrawImage(windowless_context_, rect.ToCGRect(), sub_image); | |
| 349 } else if (transparent_) { | |
| 350 CGContextClearRect(windowless_context_, rect.ToCGRect()); | |
| 351 } | |
| 352 CGContextClipToRect(windowless_context_, rect.ToCGRect()); | |
| 353 delegate_->Paint(windowless_context_, rect); | |
| 354 if (windowless_context_.get() == saved_context_weak) | |
| 355 CGContextRestoreGState(windowless_context_); | |
| 356 #else | |
| 357 windowless_canvas_->save(); | |
| 358 | |
| 359 // The given clip rect is relative to the plugin coordinate system. | |
| 360 SkRect sk_rect = { SkIntToScalar(rect.x()), | |
| 361 SkIntToScalar(rect.y()), | |
| 362 SkIntToScalar(rect.right()), | |
| 363 SkIntToScalar(rect.bottom()) }; | |
| 364 windowless_canvas_->clipRect(sk_rect); | |
| 365 | |
| 366 // Setup the background. | |
| 367 if (background_canvas_.get()) { | |
| 368 // When a background canvas is given, we're in transparent mode. This means | |
| 369 // the plugin wants to have the image of the page in the canvas it's drawing | |
| 370 // into (which is windowless_canvas_) so it can do blending. So we copy the | |
| 371 // background bitmap into the windowless_canvas_. | |
| 372 const SkBitmap& background_bitmap = | |
| 373 background_canvas_->getTopPlatformDevice().accessBitmap(false); | |
| 374 windowless_canvas_->drawBitmap(background_bitmap, 0, 0); | |
| 375 } else { | |
| 376 // In non-transparent mode, the plugin doesn't care what's underneath, so we | |
| 377 // can just give it black. | |
| 378 SkPaint black_fill_paint; | |
| 379 black_fill_paint.setARGB(0xFF, 0x00, 0x00, 0x00); | |
| 380 windowless_canvas_->drawPaint(black_fill_paint); | |
| 381 } | |
| 382 | |
| 383 // Bring the windowless_canvas_ into the window coordinate system, which is | |
| 384 // how the plugin expects to draw (since the windowless API was originally | |
| 385 // designed just for scribbling over the web page). | |
| 386 windowless_canvas_->translate(SkIntToScalar(-delegate_->GetRect().x()), | |
| 387 SkIntToScalar(-delegate_->GetRect().y())); | |
| 388 | |
| 389 // Before we send the invalidate, paint so that renderer uses the updated | |
| 390 // bitmap. | |
| 391 delegate_->Paint(windowless_canvas_.get(), offset_rect); | |
| 392 | |
| 393 windowless_canvas_->restore(); | |
| 394 #endif | |
| 395 } | |
| 396 | |
| 397 void WebPluginProxy::UpdateGeometry( | |
| 398 const gfx::Rect& window_rect, | |
| 399 const gfx::Rect& clip_rect, | |
| 400 const TransportDIB::Handle& windowless_buffer, | |
| 401 const TransportDIB::Handle& background_buffer, | |
| 402 bool transparent | |
| 403 #if defined(OS_MACOSX) | |
| 404 , | |
| 405 int ack_key | |
| 406 #endif | |
| 407 ) { | |
| 408 gfx::Rect old = delegate_->GetRect(); | |
| 409 gfx::Rect old_clip_rect = delegate_->GetClipRect(); | |
| 410 transparent_ = transparent; | |
| 411 | |
| 412 // Update the buffers before doing anything that could call into plugin code, | |
| 413 // so that we don't process buffer changes out of order if plugins make | |
| 414 // synchronous calls that lead to nested UpdateGeometry calls. | |
| 415 if (TransportDIB::is_valid(windowless_buffer)) { | |
| 416 // The plugin's rect changed, so now we have a new buffer to draw into. | |
| 417 SetWindowlessBuffer(windowless_buffer, background_buffer, window_rect); | |
| 418 } | |
| 419 | |
| 420 #if defined(OS_MACOSX) | |
| 421 delegate_->UpdateGeometryAndContext(window_rect, clip_rect, | |
| 422 windowless_context_); | |
| 423 #else | |
| 424 delegate_->UpdateGeometry(window_rect, clip_rect); | |
| 425 #endif | |
| 426 | |
| 427 // Send over any pending invalidates which occured when the plugin was | |
| 428 // off screen. | |
| 429 if (delegate_->IsWindowless() && !clip_rect.IsEmpty() && | |
| 430 !damaged_rect_.IsEmpty()) { | |
| 431 InvalidateRect(damaged_rect_); | |
| 432 } | |
| 433 | |
| 434 #if defined(OS_MACOSX) | |
| 435 // The renderer is expecting an ACK message if ack_key is not -1. | |
| 436 if (ack_key != -1) { | |
| 437 Send(new PluginHostMsg_UpdateGeometry_ACK(route_id_, ack_key)); | |
| 438 } | |
| 439 #endif | |
| 440 } | |
| 441 | |
| 442 #if defined(OS_WIN) | |
| 443 void WebPluginProxy::SetWindowlessBuffer( | |
| 444 const TransportDIB::Handle& windowless_buffer, | |
| 445 const TransportDIB::Handle& background_buffer, | |
| 446 const gfx::Rect& window_rect) { | |
| 447 // Create a canvas that will reference the shared bits. We have to handle | |
| 448 // errors here since we're mapping a large amount of memory that may not fit | |
| 449 // in our address space, or go wrong in some other way. | |
| 450 windowless_canvas_.reset(new skia::PlatformCanvas); | |
| 451 if (!windowless_canvas_->initialize( | |
| 452 window_rect.width(), | |
| 453 window_rect.height(), | |
| 454 true, | |
| 455 chrome::GetSectionFromProcess(windowless_buffer, | |
| 456 channel_->renderer_handle(), false))) { | |
| 457 windowless_canvas_.reset(); | |
| 458 background_canvas_.reset(); | |
| 459 return; | |
| 460 } | |
| 461 | |
| 462 if (background_buffer) { | |
| 463 background_canvas_.reset(new skia::PlatformCanvas); | |
| 464 if (!background_canvas_->initialize( | |
| 465 window_rect.width(), | |
| 466 window_rect.height(), | |
| 467 true, | |
| 468 chrome::GetSectionFromProcess(background_buffer, | |
| 469 channel_->renderer_handle(), false))) { | |
| 470 windowless_canvas_.reset(); | |
| 471 background_canvas_.reset(); | |
| 472 return; | |
| 473 } | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 #elif defined(OS_MACOSX) | |
| 478 | |
| 479 void WebPluginProxy::SetWindowlessBuffer( | |
| 480 const TransportDIB::Handle& windowless_buffer, | |
| 481 const TransportDIB::Handle& background_buffer, | |
| 482 const gfx::Rect& window_rect) { | |
| 483 // Convert the shared memory handle to a handle that works in our process, | |
| 484 // and then use that to create a CGContextRef. | |
| 485 windowless_dib_.reset(TransportDIB::Map(windowless_buffer)); | |
| 486 background_dib_.reset(TransportDIB::Map(background_buffer)); | |
| 487 windowless_context_.reset(CGBitmapContextCreate( | |
| 488 windowless_dib_->memory(), | |
| 489 window_rect.width(), | |
| 490 window_rect.height(), | |
| 491 8, 4 * window_rect.width(), | |
| 492 base::mac::GetSystemColorSpace(), | |
| 493 kCGImageAlphaPremultipliedFirst | | |
| 494 kCGBitmapByteOrder32Host)); | |
| 495 CGContextTranslateCTM(windowless_context_, 0, window_rect.height()); | |
| 496 CGContextScaleCTM(windowless_context_, 1, -1); | |
| 497 if (background_dib_.get()) { | |
| 498 background_context_.reset(CGBitmapContextCreate( | |
| 499 background_dib_->memory(), | |
| 500 window_rect.width(), | |
| 501 window_rect.height(), | |
| 502 8, 4 * window_rect.width(), | |
| 503 base::mac::GetSystemColorSpace(), | |
| 504 kCGImageAlphaPremultipliedFirst | | |
| 505 kCGBitmapByteOrder32Host)); | |
| 506 CGContextTranslateCTM(background_context_, 0, window_rect.height()); | |
| 507 CGContextScaleCTM(background_context_, 1, -1); | |
| 508 } | |
| 509 } | |
| 510 | |
| 511 #elif defined(USE_X11) | |
| 512 | |
| 513 void WebPluginProxy::SetWindowlessBuffer( | |
| 514 const TransportDIB::Handle& windowless_buffer, | |
| 515 const TransportDIB::Handle& background_buffer, | |
| 516 const gfx::Rect& window_rect) { | |
| 517 int width = window_rect.width(); | |
| 518 int height = window_rect.height(); | |
| 519 windowless_dib_.reset(TransportDIB::Map(windowless_buffer)); | |
| 520 if (windowless_dib_.get()) { | |
| 521 windowless_canvas_.reset(windowless_dib_->GetPlatformCanvas(width, height)); | |
| 522 } else { | |
| 523 // This can happen if the renderer has already destroyed the TransportDIB | |
| 524 // by the time we receive the handle, e.g. in case of multiple resizes. | |
| 525 windowless_canvas_.reset(); | |
| 526 } | |
| 527 background_dib_.reset(TransportDIB::Map(background_buffer)); | |
| 528 if (background_dib_.get()) { | |
| 529 background_canvas_.reset(background_dib_->GetPlatformCanvas(width, height)); | |
| 530 } else { | |
| 531 background_canvas_.reset(); | |
| 532 } | |
| 533 | |
| 534 // If SHM pixmaps support is available, create a SHM pixmap and | |
| 535 // pass it to the delegate for windowless plugin painting. | |
| 536 if (delegate_->IsWindowless() && use_shm_pixmap_ && windowless_dib_.get()) { | |
| 537 Display* display = ui::GetXDisplay(); | |
| 538 XID root_window = ui::GetX11RootWindow(); | |
| 539 XShmSegmentInfo shminfo = {0}; | |
| 540 | |
| 541 if (windowless_shm_pixmap_ != None) | |
| 542 XFreePixmap(display, windowless_shm_pixmap_); | |
| 543 | |
| 544 shminfo.shmseg = windowless_dib_->MapToX(display); | |
| 545 // Create a shared memory pixmap based on the image buffer. | |
| 546 windowless_shm_pixmap_ = XShmCreatePixmap(display, root_window, | |
| 547 NULL, &shminfo, | |
| 548 width, height, | |
| 549 DefaultDepth(display, 0)); | |
| 550 | |
| 551 delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap_); | |
| 552 } | |
| 553 } | |
| 554 | |
| 555 #endif | |
| 556 | |
| 557 void WebPluginProxy::CancelDocumentLoad() { | |
| 558 Send(new PluginHostMsg_CancelDocumentLoad(route_id_)); | |
| 559 } | |
| 560 | |
| 561 void WebPluginProxy::InitiateHTTPRangeRequest( | |
| 562 const char* url, const char* range_info, int range_request_id) { | |
| 563 Send(new PluginHostMsg_InitiateHTTPRangeRequest( | |
| 564 route_id_, url, range_info, range_request_id)); | |
| 565 } | |
| 566 | |
| 567 void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id, | |
| 568 bool defer) { | |
| 569 Send(new PluginHostMsg_DeferResourceLoading(route_id_, resource_id, defer)); | |
| 570 } | |
| 571 | |
| 572 #if defined(OS_MACOSX) | |
| 573 void WebPluginProxy::FocusChanged(bool focused) { | |
| 574 IPC::Message* msg = new PluginHostMsg_FocusChanged(route_id_, focused); | |
| 575 Send(msg); | |
| 576 } | |
| 577 | |
| 578 void WebPluginProxy::StartIme() { | |
| 579 IPC::Message* msg = new PluginHostMsg_StartIme(route_id_); | |
| 580 // This message can be sent during event-handling, and needs to be delivered | |
| 581 // within that context. | |
| 582 msg->set_unblock(true); | |
| 583 Send(msg); | |
| 584 } | |
| 585 | |
| 586 void WebPluginProxy::BindFakePluginWindowHandle(bool opaque) { | |
| 587 Send(new PluginHostMsg_BindFakePluginWindowHandle(route_id_, opaque)); | |
| 588 } | |
| 589 | |
| 590 WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface() { | |
| 591 if (!accelerated_surface_.get()) | |
| 592 accelerated_surface_.reset(new WebPluginAcceleratedSurfaceProxy(this)); | |
| 593 return accelerated_surface_.get(); | |
| 594 } | |
| 595 | |
| 596 void WebPluginProxy::AcceleratedFrameBuffersDidSwap( | |
| 597 gfx::PluginWindowHandle window, uint64 surface_id) { | |
| 598 Send(new PluginHostMsg_AcceleratedSurfaceBuffersSwapped( | |
| 599 route_id_, window, surface_id)); | |
| 600 } | |
| 601 | |
| 602 void WebPluginProxy::SetAcceleratedSurface( | |
| 603 gfx::PluginWindowHandle window, | |
| 604 const gfx::Size& size, | |
| 605 uint64 accelerated_surface_identifier) { | |
| 606 Send(new PluginHostMsg_AcceleratedSurfaceSetIOSurface( | |
| 607 route_id_, window, size.width(), size.height(), | |
| 608 accelerated_surface_identifier)); | |
| 609 } | |
| 610 | |
| 611 void WebPluginProxy::SetAcceleratedDIB( | |
| 612 gfx::PluginWindowHandle window, | |
| 613 const gfx::Size& size, | |
| 614 const TransportDIB::Handle& dib_handle) { | |
| 615 Send(new PluginHostMsg_AcceleratedSurfaceSetTransportDIB( | |
| 616 route_id_, window, size.width(), size.height(), dib_handle)); | |
| 617 } | |
| 618 | |
| 619 void WebPluginProxy::AllocSurfaceDIB(const size_t size, | |
| 620 TransportDIB::Handle* dib_handle) { | |
| 621 Send(new PluginHostMsg_AllocTransportDIB(route_id_, size, dib_handle)); | |
| 622 } | |
| 623 | |
| 624 void WebPluginProxy::FreeSurfaceDIB(TransportDIB::Id dib_id) { | |
| 625 Send(new PluginHostMsg_FreeTransportDIB(route_id_, dib_id)); | |
| 626 } | |
| 627 #endif | |
| 628 | |
| 629 void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) { | |
| 630 content::GetContentClient()->SetActiveURL(page_url_); | |
| 631 | |
| 632 Paint(damaged_rect); | |
| 633 Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect)); | |
| 634 } | |
| 635 | |
| 636 bool WebPluginProxy::IsOffTheRecord() { | |
| 637 return channel_->incognito(); | |
| 638 } | |
| 639 | |
| 640 void WebPluginProxy::ResourceClientDeleted( | |
| 641 WebPluginResourceClient* resource_client) { | |
| 642 ResourceClientMap::iterator index = resource_clients_.begin(); | |
| 643 while (index != resource_clients_.end()) { | |
| 644 WebPluginResourceClient* client = (*index).second; | |
| 645 | |
| 646 if (client == resource_client) { | |
| 647 resource_clients_.erase(index++); | |
| 648 } else { | |
| 649 index++; | |
| 650 } | |
| 651 } | |
| 652 } | |
| 653 | |
| 654 void WebPluginProxy::URLRedirectResponse(bool allow, int resource_id) { | |
| 655 Send(new PluginHostMsg_URLRedirectResponse(route_id_, allow, resource_id)); | |
| 656 } | |
| OLD | NEW |