| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/proxy/ppb_image_data_proxy.h" | 5 #include "ppapi/proxy/ppb_image_data_proxy.h" |
| 6 | 6 |
| 7 #include <string.h> // For memcpy | 7 #include <string.h> // For memcpy |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 }; | 113 }; |
| 114 | 114 |
| 115 // ImageDataInstanceCache ------------------------------------------------------ | 115 // ImageDataInstanceCache ------------------------------------------------------ |
| 116 | 116 |
| 117 // Per-instance cache of image datas. | 117 // Per-instance cache of image datas. |
| 118 class ImageDataInstanceCache { | 118 class ImageDataInstanceCache { |
| 119 public: | 119 public: |
| 120 ImageDataInstanceCache() : next_insertion_point_(0) {} | 120 ImageDataInstanceCache() : next_insertion_point_(0) {} |
| 121 | 121 |
| 122 // These functions have the same spec as the ones in ImageDataCache. | 122 // These functions have the same spec as the ones in ImageDataCache. |
| 123 scoped_refptr<ImageData> Get(int width, int height, | 123 scoped_refptr<ImageData> Get(PPB_ImageData_Shared::ImageDataType type, |
| 124 int width, int height, |
| 124 PP_ImageDataFormat format); | 125 PP_ImageDataFormat format); |
| 125 void Add(ImageData* image_data); | 126 void Add(ImageData* image_data); |
| 126 void ImageDataUsable(ImageData* image_data); | 127 void ImageDataUsable(ImageData* image_data); |
| 127 | 128 |
| 128 // Expires old entries. Returns true if there are still entries in the list, | 129 // Expires old entries. Returns true if there are still entries in the list, |
| 129 // false if this instance cache is now empty. | 130 // false if this instance cache is now empty. |
| 130 bool ExpireEntries(); | 131 bool ExpireEntries(); |
| 131 | 132 |
| 132 private: | 133 private: |
| 133 void IncrementInsertionPoint(); | 134 void IncrementInsertionPoint(); |
| 134 | 135 |
| 135 // We'll store this many ImageDatas per instance. | 136 // We'll store this many ImageDatas per instance. |
| 136 const static int kCacheSize = 2; | 137 const static int kCacheSize = 2; |
| 137 | 138 |
| 138 ImageDataCacheEntry images_[kCacheSize]; | 139 ImageDataCacheEntry images_[kCacheSize]; |
| 139 | 140 |
| 140 // Index into cache where the next item will go. | 141 // Index into cache where the next item will go. |
| 141 int next_insertion_point_; | 142 int next_insertion_point_; |
| 142 }; | 143 }; |
| 143 | 144 |
| 144 scoped_refptr<ImageData> ImageDataInstanceCache::Get( | 145 scoped_refptr<ImageData> ImageDataInstanceCache::Get( |
| 146 PPB_ImageData_Shared::ImageDataType type, |
| 145 int width, int height, | 147 int width, int height, |
| 146 PP_ImageDataFormat format) { | 148 PP_ImageDataFormat format) { |
| 147 // Just do a brute-force search since the cache is so small. | 149 // Just do a brute-force search since the cache is so small. |
| 148 for (int i = 0; i < kCacheSize; i++) { | 150 for (int i = 0; i < kCacheSize; i++) { |
| 149 if (!images_[i].usable) | 151 if (!images_[i].usable) |
| 150 continue; | 152 continue; |
| 153 if (!images_[i].image->type() == type) |
| 154 continue; |
| 151 const PP_ImageDataDesc& desc = images_[i].image->desc(); | 155 const PP_ImageDataDesc& desc = images_[i].image->desc(); |
| 152 if (desc.format == format && | 156 if (desc.format == format && |
| 153 desc.size.width == width && desc.size.height == height) { | 157 desc.size.width == width && desc.size.height == height) { |
| 154 scoped_refptr<ImageData> ret(images_[i].image); | 158 scoped_refptr<ImageData> ret(images_[i].image); |
| 155 images_[i] = ImageDataCacheEntry(); | 159 images_[i] = ImageDataCacheEntry(); |
| 156 | 160 |
| 157 // Since we just removed an item, this entry is the best place to insert | 161 // Since we just removed an item, this entry is the best place to insert |
| 158 // a subsequent one. | 162 // a subsequent one. |
| 159 next_insertion_point_ = i; | 163 next_insertion_point_ = i; |
| 160 return ret; | 164 return ret; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 | 220 |
| 217 // ImageDataCache -------------------------------------------------------------- | 221 // ImageDataCache -------------------------------------------------------------- |
| 218 | 222 |
| 219 class ImageDataCache { | 223 class ImageDataCache { |
| 220 public: | 224 public: |
| 221 ImageDataCache() : weak_factory_(this) {} | 225 ImageDataCache() : weak_factory_(this) {} |
| 222 ~ImageDataCache() {} | 226 ~ImageDataCache() {} |
| 223 | 227 |
| 224 static ImageDataCache* GetInstance(); | 228 static ImageDataCache* GetInstance(); |
| 225 | 229 |
| 226 // Retrieves an image data from the cache of the specified size and format if | 230 // Retrieves an image data from the cache of the specified type, size and |
| 227 // one exists. If one doesn't exist, this will return a null refptr. | 231 // format if one exists. If one doesn't exist, this will return a null refptr. |
| 228 scoped_refptr<ImageData> Get(PP_Instance instance, | 232 scoped_refptr<ImageData> Get(PP_Instance instance, |
| 233 PPB_ImageData_Shared::ImageDataType type, |
| 229 int width, int height, | 234 int width, int height, |
| 230 PP_ImageDataFormat format); | 235 PP_ImageDataFormat format); |
| 231 | 236 |
| 232 // Adds the given image data to the cache. There should be no plugin | 237 // Adds the given image data to the cache. There should be no plugin |
| 233 // references to it. This may delete an older item from the cache. | 238 // references to it. This may delete an older item from the cache. |
| 234 void Add(ImageData* image_data); | 239 void Add(ImageData* image_data); |
| 235 | 240 |
| 236 // Notification from the renderer that the given image data is usable. | 241 // Notification from the renderer that the given image data is usable. |
| 237 void ImageDataUsable(ImageData* image_data); | 242 void ImageDataUsable(ImageData* image_data); |
| 238 | 243 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 255 | 260 |
| 256 DISALLOW_COPY_AND_ASSIGN(ImageDataCache); | 261 DISALLOW_COPY_AND_ASSIGN(ImageDataCache); |
| 257 }; | 262 }; |
| 258 | 263 |
| 259 // static | 264 // static |
| 260 ImageDataCache* ImageDataCache::GetInstance() { | 265 ImageDataCache* ImageDataCache::GetInstance() { |
| 261 return Singleton<ImageDataCache, | 266 return Singleton<ImageDataCache, |
| 262 LeakySingletonTraits<ImageDataCache> >::get(); | 267 LeakySingletonTraits<ImageDataCache> >::get(); |
| 263 } | 268 } |
| 264 | 269 |
| 265 scoped_refptr<ImageData> ImageDataCache::Get(PP_Instance instance, | 270 scoped_refptr<ImageData> ImageDataCache::Get( |
| 266 int width, int height, | 271 PP_Instance instance, |
| 267 PP_ImageDataFormat format) { | 272 PPB_ImageData_Shared::ImageDataType type, |
| 273 int width, int height, |
| 274 PP_ImageDataFormat format) { |
| 268 CacheMap::iterator found = cache_.find(instance); | 275 CacheMap::iterator found = cache_.find(instance); |
| 269 if (found == cache_.end()) | 276 if (found == cache_.end()) |
| 270 return scoped_refptr<ImageData>(); | 277 return scoped_refptr<ImageData>(); |
| 271 return found->second.Get(width, height, format); | 278 return found->second.Get(type, width, height, format); |
| 272 } | 279 } |
| 273 | 280 |
| 274 void ImageDataCache::Add(ImageData* image_data) { | 281 void ImageDataCache::Add(ImageData* image_data) { |
| 275 cache_[image_data->pp_instance()].Add(image_data); | 282 cache_[image_data->pp_instance()].Add(image_data); |
| 276 | 283 |
| 277 // Schedule a timer to invalidate this entry. | 284 // Schedule a timer to invalidate this entry. |
| 278 base::MessageLoop::current()->PostDelayedTask( | 285 base::MessageLoop::current()->PostDelayedTask( |
| 279 FROM_HERE, | 286 FROM_HERE, |
| 280 RunWhileLocked(base::Bind(&ImageDataCache::OnTimer, | 287 RunWhileLocked(base::Bind(&ImageDataCache::OnTimer, |
| 281 weak_factory_.GetWeakPtr(), | 288 weak_factory_.GetWeakPtr(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 300 if (!found->second.ExpireEntries()) { | 307 if (!found->second.ExpireEntries()) { |
| 301 // There are no more entries for this instance, remove it from the cache. | 308 // There are no more entries for this instance, remove it from the cache. |
| 302 cache_.erase(found); | 309 cache_.erase(found); |
| 303 } | 310 } |
| 304 } | 311 } |
| 305 | 312 |
| 306 } // namespace | 313 } // namespace |
| 307 | 314 |
| 308 // ImageData ------------------------------------------------------------------- | 315 // ImageData ------------------------------------------------------------------- |
| 309 | 316 |
| 310 #if !defined(OS_NACL) | |
| 311 ImageData::ImageData(const HostResource& resource, | 317 ImageData::ImageData(const HostResource& resource, |
| 312 const PP_ImageDataDesc& desc, | 318 PPB_ImageData_Shared::ImageDataType type, |
| 313 ImageHandle handle) | 319 const PP_ImageDataDesc& desc) |
| 314 : Resource(OBJECT_IS_PROXY, resource), | 320 : Resource(OBJECT_IS_PROXY, resource), |
| 321 type_(type), |
| 315 desc_(desc), | 322 desc_(desc), |
| 316 is_candidate_for_reuse_(false) { | 323 is_candidate_for_reuse_(false) { |
| 317 #if defined(OS_WIN) | |
| 318 transport_dib_.reset(TransportDIB::CreateWithHandle(handle)); | |
| 319 #else | |
| 320 transport_dib_.reset(TransportDIB::Map(handle)); | |
| 321 #endif // defined(OS_WIN) | |
| 322 } | 324 } |
| 323 #else // !defined(OS_NACL) | |
| 324 | |
| 325 ImageData::ImageData(const HostResource& resource, | |
| 326 const PP_ImageDataDesc& desc, | |
| 327 const base::SharedMemoryHandle& handle) | |
| 328 : Resource(OBJECT_IS_PROXY, resource), | |
| 329 desc_(desc), | |
| 330 shm_(handle, false /* read_only */), | |
| 331 size_(desc.size.width * desc.size.height * 4), | |
| 332 map_count_(0), | |
| 333 is_candidate_for_reuse_(false) { | |
| 334 } | |
| 335 #endif // else, !defined(OS_NACL) | |
| 336 | 325 |
| 337 ImageData::~ImageData() { | 326 ImageData::~ImageData() { |
| 338 } | 327 } |
| 339 | 328 |
| 340 PPB_ImageData_API* ImageData::AsPPB_ImageData_API() { | 329 PPB_ImageData_API* ImageData::AsPPB_ImageData_API() { |
| 341 return this; | 330 return this; |
| 342 } | 331 } |
| 343 | 332 |
| 344 void ImageData::LastPluginRefWasDeleted() { | 333 void ImageData::LastPluginRefWasDeleted() { |
| 345 // The plugin no longer needs this ImageData, add it to our cache if it's | 334 // The plugin no longer needs this ImageData, add it to our cache if it's |
| 346 // been used in a ReplaceContents. These are the ImageDatas that the renderer | 335 // been used in a ReplaceContents. These are the ImageDatas that the renderer |
| 347 // will send back ImageDataUsable messages for. | 336 // will send back ImageDataUsable messages for. |
| 348 if (is_candidate_for_reuse_) | 337 if (is_candidate_for_reuse_) |
| 349 ImageDataCache::GetInstance()->Add(this); | 338 ImageDataCache::GetInstance()->Add(this); |
| 350 } | 339 } |
| 351 | 340 |
| 352 void ImageData::InstanceWasDeleted() { | 341 void ImageData::InstanceWasDeleted() { |
| 353 ImageDataCache::GetInstance()->DidDeleteInstance(pp_instance()); | 342 ImageDataCache::GetInstance()->DidDeleteInstance(pp_instance()); |
| 354 } | 343 } |
| 355 | 344 |
| 356 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) { | 345 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) { |
| 357 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc)); | 346 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc)); |
| 358 return PP_TRUE; | 347 return PP_TRUE; |
| 359 } | 348 } |
| 360 | 349 |
| 361 void* ImageData::Map() { | 350 int32_t ImageData::GetSharedMemory(int* /* handle */, |
| 362 #if defined(OS_NACL) | 351 uint32_t* /* byte_count */) { |
| 363 if (map_count_++ == 0) | 352 // Not supported in the proxy (this method is for actually implementing the |
| 364 shm_.Map(size_); | 353 // proxy in the host). |
| 365 return shm_.memory(); | 354 return PP_ERROR_NOACCESS; |
| 355 } |
| 356 |
| 357 void ImageData::SetIsCandidateForReuse() { |
| 358 is_candidate_for_reuse_ = true; |
| 359 } |
| 360 |
| 361 void ImageData::RecycleToPlugin(bool zero_contents) { |
| 362 is_candidate_for_reuse_ = false; |
| 363 if (zero_contents) { |
| 364 void* data = Map(); |
| 365 memset(data, 0, desc_.stride * desc_.size.height); |
| 366 Unmap(); |
| 367 } |
| 368 } |
| 369 |
| 370 // PlatformImageData ----------------------------------------------------------- |
| 371 |
| 372 #if !defined(OS_NACL) |
| 373 PlatformImageData::PlatformImageData(const HostResource& resource, |
| 374 const PP_ImageDataDesc& desc, |
| 375 ImageHandle handle) |
| 376 : ImageData(resource, PPB_ImageData_Shared::PLATFORM, desc) { |
| 377 #if defined(OS_WIN) |
| 378 transport_dib_.reset(TransportDIB::CreateWithHandle(handle)); |
| 366 #else | 379 #else |
| 380 transport_dib_.reset(TransportDIB::Map(handle)); |
| 381 #endif // defined(OS_WIN) |
| 382 } |
| 383 |
| 384 PlatformImageData::~PlatformImageData() { |
| 385 } |
| 386 |
| 387 void* PlatformImageData::Map() { |
| 367 if (!mapped_canvas_.get()) { | 388 if (!mapped_canvas_.get()) { |
| 368 mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width, | 389 mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width, |
| 369 desc_.size.height)); | 390 desc_.size.height)); |
| 370 if (!mapped_canvas_.get()) | 391 if (!mapped_canvas_.get()) |
| 371 return NULL; | 392 return NULL; |
| 372 } | 393 } |
| 373 const SkBitmap& bitmap = | 394 const SkBitmap& bitmap = |
| 374 skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true); | 395 skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true); |
| 375 | 396 |
| 376 bitmap.lockPixels(); | 397 bitmap.lockPixels(); |
| 377 return bitmap.getAddr(0, 0); | 398 return bitmap.getAddr(0, 0); |
| 378 #endif | |
| 379 } | 399 } |
| 380 | 400 |
| 381 void ImageData::Unmap() { | 401 void PlatformImageData::Unmap() { |
| 382 #if defined(OS_NACL) | |
| 383 if (--map_count_ == 0) | |
| 384 shm_.Unmap(); | |
| 385 #else | |
| 386 // TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't | 402 // TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't |
| 387 // possible since deleting the TransportDIB also frees all the handles. | 403 // possible since deleting the TransportDIB also frees all the handles. |
| 388 // We need to add a method to TransportDIB to release the handles. | 404 // We need to add a method to TransportDIB to release the handles. |
| 389 #endif | |
| 390 } | 405 } |
| 391 | 406 |
| 392 int32_t ImageData::GetSharedMemory(int* /* handle */, | 407 SkCanvas* PlatformImageData::GetPlatformCanvas() { |
| 393 uint32_t* /* byte_count */) { | 408 return mapped_canvas_.get(); |
| 394 // Not supported in the proxy (this method is for actually implementing the | |
| 395 // proxy in the host). | |
| 396 return PP_ERROR_NOACCESS; | |
| 397 } | 409 } |
| 398 | 410 |
| 399 SkCanvas* ImageData::GetPlatformCanvas() { | 411 SkCanvas* PlatformImageData::GetCanvas() { |
| 400 #if defined(OS_NACL) | |
| 401 return NULL; // No canvas in NaCl. | |
| 402 #else | |
| 403 return mapped_canvas_.get(); | 412 return mapped_canvas_.get(); |
| 404 #endif | |
| 405 } | 413 } |
| 406 | 414 |
| 407 SkCanvas* ImageData::GetCanvas() { | |
| 408 #if defined(OS_NACL) | |
| 409 return NULL; // No canvas in NaCl. | |
| 410 #else | |
| 411 return mapped_canvas_.get(); | |
| 412 #endif | |
| 413 } | |
| 414 | |
| 415 void ImageData::SetIsCandidateForReuse() { | |
| 416 is_candidate_for_reuse_ = true; | |
| 417 } | |
| 418 | |
| 419 void ImageData::RecycleToPlugin(bool zero_contents) { | |
| 420 is_candidate_for_reuse_ = false; | |
| 421 if (zero_contents) { | |
| 422 void* data = Map(); | |
| 423 memset(data, 0, desc_.stride * desc_.size.height); | |
| 424 Unmap(); | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 #if !defined(OS_NACL) | |
| 429 // static | 415 // static |
| 430 ImageHandle ImageData::NullHandle() { | 416 ImageHandle PlatformImageData::NullHandle() { |
| 431 #if defined(OS_WIN) | 417 #if defined(OS_WIN) |
| 432 return NULL; | 418 return NULL; |
| 433 #elif defined(TOOLKIT_GTK) | 419 #elif defined(TOOLKIT_GTK) |
| 434 return 0; | 420 return 0; |
| 435 #else | 421 #else |
| 436 return ImageHandle(); | 422 return ImageHandle(); |
| 437 #endif | 423 #endif |
| 438 } | 424 } |
| 439 | 425 |
| 440 ImageHandle ImageData::HandleFromInt(int32_t i) { | 426 ImageHandle PlatformImageData::HandleFromInt(int32_t i) { |
| 441 #if defined(OS_WIN) | 427 #if defined(OS_WIN) |
| 442 return reinterpret_cast<ImageHandle>(i); | 428 return reinterpret_cast<ImageHandle>(i); |
| 443 #elif defined(TOOLKIT_GTK) | 429 #elif defined(TOOLKIT_GTK) |
| 444 return static_cast<ImageHandle>(i); | 430 return static_cast<ImageHandle>(i); |
| 445 #else | 431 #else |
| 446 return ImageHandle(i, false); | 432 return ImageHandle(i, false); |
| 447 #endif | 433 #endif |
| 448 } | 434 } |
| 449 #endif // !defined(OS_NACL) | 435 #endif // !defined(OS_NACL) |
| 450 | 436 |
| 437 // SimpleImageData ------------------------------------------------------------- |
| 438 |
| 439 SimpleImageData::SimpleImageData(const HostResource& resource, |
| 440 const PP_ImageDataDesc& desc, |
| 441 const base::SharedMemoryHandle& handle) |
| 442 : ImageData(resource, PPB_ImageData_Shared::SIMPLE, desc), |
| 443 shm_(handle, false /* read_only */), |
| 444 size_(desc.size.width * desc.size.height * 4), |
| 445 map_count_(0) { |
| 446 } |
| 447 |
| 448 SimpleImageData::~SimpleImageData() { |
| 449 } |
| 450 |
| 451 void* SimpleImageData::Map() { |
| 452 if (map_count_++ == 0) |
| 453 shm_.Map(size_); |
| 454 return shm_.memory(); |
| 455 } |
| 456 |
| 457 void SimpleImageData::Unmap() { |
| 458 if (--map_count_ == 0) |
| 459 shm_.Unmap(); |
| 460 } |
| 461 |
| 462 SkCanvas* SimpleImageData::GetPlatformCanvas() { |
| 463 return NULL; // No canvas available. |
| 464 } |
| 465 |
| 466 SkCanvas* SimpleImageData::GetCanvas() { |
| 467 return NULL; // No canvas available. |
| 468 } |
| 469 |
| 451 // PPB_ImageData_Proxy --------------------------------------------------------- | 470 // PPB_ImageData_Proxy --------------------------------------------------------- |
| 452 | 471 |
| 453 PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher) | 472 PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher) |
| 454 : InterfaceProxy(dispatcher) { | 473 : InterfaceProxy(dispatcher) { |
| 455 } | 474 } |
| 456 | 475 |
| 457 PPB_ImageData_Proxy::~PPB_ImageData_Proxy() { | 476 PPB_ImageData_Proxy::~PPB_ImageData_Proxy() { |
| 458 } | 477 } |
| 459 | 478 |
| 460 // static | 479 // static |
| 461 PP_Resource PPB_ImageData_Proxy::CreateProxyResource(PP_Instance instance, | 480 PP_Resource PPB_ImageData_Proxy::CreateProxyResource( |
| 462 PP_ImageDataFormat format, | 481 PP_Instance instance, |
| 463 const PP_Size& size, | 482 PPB_ImageData_Shared::ImageDataType type, |
| 464 PP_Bool init_to_zero) { | 483 PP_ImageDataFormat format, |
| 484 const PP_Size& size, |
| 485 PP_Bool init_to_zero) { |
| 465 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 486 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| 466 if (!dispatcher) | 487 if (!dispatcher) |
| 467 return 0; | 488 return 0; |
| 468 | 489 |
| 469 // Check the cache. | 490 // Check the cache. |
| 470 scoped_refptr<ImageData> cached_image_data = | 491 scoped_refptr<ImageData> cached_image_data = |
| 471 ImageDataCache::GetInstance()->Get(instance, size.width, size.height, | 492 ImageDataCache::GetInstance()->Get(instance, type, |
| 472 format); | 493 size.width, size.height, format); |
| 473 if (cached_image_data.get()) { | 494 if (cached_image_data.get()) { |
| 474 // We have one we can re-use rather than allocating a new one. | 495 // We have one we can re-use rather than allocating a new one. |
| 475 cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero)); | 496 cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero)); |
| 476 return cached_image_data->GetReference(); | 497 return cached_image_data->GetReference(); |
| 477 } | 498 } |
| 478 | 499 |
| 479 HostResource result; | 500 HostResource result; |
| 480 std::string image_data_desc; | 501 PP_ImageDataDesc desc; |
| 481 #if defined(OS_NACL) | 502 switch (type) { |
| 482 ppapi::proxy::SerializedHandle image_handle_wrapper; | 503 case PPB_ImageData_Shared::SIMPLE: { |
| 483 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl( | 504 ppapi::proxy::SerializedHandle image_handle_wrapper; |
| 484 kApiID, instance, format, size, init_to_zero, | 505 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateSimple( |
| 485 &result, &image_data_desc, &image_handle_wrapper)); | 506 kApiID, instance, format, size, init_to_zero, |
| 486 if (!image_handle_wrapper.is_shmem()) | 507 &result, &desc, &image_handle_wrapper)); |
| 487 return 0; | 508 if (image_handle_wrapper.is_shmem()) { |
| 488 base::SharedMemoryHandle image_handle = image_handle_wrapper.shmem(); | 509 base::SharedMemoryHandle image_handle = image_handle_wrapper.shmem(); |
| 510 if (!result.is_null()) |
| 511 return |
| 512 (new SimpleImageData(result, desc, image_handle))->GetReference(); |
| 513 } |
| 514 break; |
| 515 } |
| 516 case PPB_ImageData_Shared::PLATFORM: { |
| 517 #if !defined(OS_NACL) |
| 518 ImageHandle image_handle = PlatformImageData::NullHandle(); |
| 519 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreatePlatform( |
| 520 kApiID, instance, format, size, init_to_zero, |
| 521 &result, &desc, &image_handle)); |
| 522 if (!result.is_null()) |
| 523 return |
| 524 (new PlatformImageData(result, desc, image_handle))->GetReference(); |
| 489 #else | 525 #else |
| 490 ImageHandle image_handle = ImageData::NullHandle(); | 526 // PlatformImageData shouldn't be created in untrusted code. |
| 491 dispatcher->Send(new PpapiHostMsg_PPBImageData_Create( | 527 NOTREACHED(); |
| 492 kApiID, instance, format, size, init_to_zero, | |
| 493 &result, &image_data_desc, &image_handle)); | |
| 494 #endif | 528 #endif |
| 529 break; |
| 530 } |
| 531 } |
| 495 | 532 |
| 496 if (result.is_null() || image_data_desc.size() != sizeof(PP_ImageDataDesc)) | 533 return 0; |
| 497 return 0; | |
| 498 | |
| 499 // We serialize the PP_ImageDataDesc just by copying to a string. | |
| 500 PP_ImageDataDesc desc; | |
| 501 memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc)); | |
| 502 | |
| 503 return (new ImageData(result, desc, image_handle))->GetReference(); | |
| 504 } | 534 } |
| 505 | 535 |
| 506 bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) { | 536 bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) { |
| 507 bool handled = true; | 537 bool handled = true; |
| 508 IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg) | 538 IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg) |
| 509 #if !defined(OS_NACL) | 539 #if !defined(OS_NACL) |
| 510 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnHostMsgCreate) | 540 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreatePlatform, |
| 511 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateNaCl, | 541 OnHostMsgCreatePlatform) |
| 512 OnHostMsgCreateNaCl) | 542 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateSimple, |
| 543 OnHostMsgCreateSimple) |
| 513 #endif | 544 #endif |
| 514 IPC_MESSAGE_HANDLER(PpapiMsg_PPBImageData_NotifyUnusedImageData, | 545 IPC_MESSAGE_HANDLER(PpapiMsg_PPBImageData_NotifyUnusedImageData, |
| 515 OnPluginMsgNotifyUnusedImageData) | 546 OnPluginMsgNotifyUnusedImageData) |
| 516 | 547 |
| 517 IPC_MESSAGE_UNHANDLED(handled = false) | 548 IPC_MESSAGE_UNHANDLED(handled = false) |
| 518 IPC_END_MESSAGE_MAP() | 549 IPC_END_MESSAGE_MAP() |
| 519 return handled; | 550 return handled; |
| 520 } | 551 } |
| 521 | 552 |
| 522 #if !defined(OS_NACL) | 553 #if !defined(OS_NACL) |
| 523 // static | 554 // static |
| 524 PP_Resource PPB_ImageData_Proxy::CreateImageData( | 555 PP_Resource PPB_ImageData_Proxy::CreateImageData( |
| 525 PP_Instance instance, | 556 PP_Instance instance, |
| 557 PPB_ImageData_Shared::ImageDataType type, |
| 526 PP_ImageDataFormat format, | 558 PP_ImageDataFormat format, |
| 527 const PP_Size& size, | 559 const PP_Size& size, |
| 528 bool init_to_zero, | 560 bool init_to_zero, |
| 529 bool is_nacl_plugin, | |
| 530 PP_ImageDataDesc* desc, | 561 PP_ImageDataDesc* desc, |
| 531 IPC::PlatformFileForTransit* image_handle, | 562 IPC::PlatformFileForTransit* image_handle, |
| 532 uint32_t* byte_count) { | 563 uint32_t* byte_count) { |
| 533 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); | 564 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); |
| 534 if (!dispatcher) | 565 if (!dispatcher) |
| 535 return 0; | 566 return 0; |
| 536 | 567 |
| 537 thunk::EnterResourceCreation enter(instance); | 568 thunk::EnterResourceCreation enter(instance); |
| 538 if (enter.failed()) | 569 if (enter.failed()) |
| 539 return 0; | 570 return 0; |
| 540 | 571 |
| 541 PP_Bool pp_init_to_zero = init_to_zero ? PP_TRUE : PP_FALSE; | 572 PP_Bool pp_init_to_zero = init_to_zero ? PP_TRUE : PP_FALSE; |
| 542 ppapi::ScopedPPResource resource( | 573 ppapi::ScopedPPResource resource( |
| 543 ppapi::ScopedPPResource::PassRef(), | 574 ppapi::ScopedPPResource::PassRef(), |
| 544 is_nacl_plugin ? | 575 enter.functions()->CreateImageData(instance, type, |
| 545 enter.functions()->CreateImageDataNaCl(instance, format, &size, | 576 format, &size, pp_init_to_zero)); |
| 546 pp_init_to_zero) : | |
| 547 enter.functions()->CreateImageData(instance, format, &size, | |
| 548 pp_init_to_zero)); | |
| 549 if (!resource.get()) | 577 if (!resource.get()) |
| 550 return 0; | 578 return 0; |
| 551 | 579 |
| 552 thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource.get(), | 580 thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource.get(), |
| 553 false); | 581 false); |
| 554 if (enter_resource.object()->Describe(desc) != PP_TRUE) { | 582 if (enter_resource.object()->Describe(desc) != PP_TRUE) { |
| 555 DVLOG(1) << "CreateImageData failed: could not Describe"; | 583 DVLOG(1) << "CreateImageData failed: could not Describe"; |
| 556 return 0; | 584 return 0; |
| 557 } | 585 } |
| 558 | 586 |
| 559 int local_fd = 0; | 587 int local_fd = 0; |
| 560 if (enter_resource.object()->GetSharedMemory(&local_fd, | 588 if (enter_resource.object()->GetSharedMemory(&local_fd, |
| 561 byte_count) != PP_OK) { | 589 byte_count) != PP_OK) { |
| 562 DVLOG(1) << "CreateImageData failed: could not GetSharedMemory"; | 590 DVLOG(1) << "CreateImageData failed: could not GetSharedMemory"; |
| 563 return 0; | 591 return 0; |
| 564 } | 592 } |
| 565 | 593 |
| 566 #if defined(OS_WIN) | 594 #if defined(OS_WIN) |
| 567 *image_handle = dispatcher->ShareHandleWithRemote( | 595 *image_handle = dispatcher->ShareHandleWithRemote( |
| 568 reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false); | 596 reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false); |
| 569 #elif defined(TOOLKIT_GTK) | 597 #elif defined(TOOLKIT_GTK) |
| 570 // On X Windows, a non-nacl handle is a SysV shared memory key. | 598 // On X Windows, a PlatformImageData is backed by a SysV shared memory key, |
| 571 if (is_nacl_plugin) | 599 // so embed that in a fake PlatformFileForTransit and don't share it across |
| 600 // processes. |
| 601 if (type == PPB_ImageData_Shared::PLATFORM) |
| 602 *image_handle = IPC::PlatformFileForTransit(local_fd, false); |
| 603 else |
| 572 *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); | 604 *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); |
| 573 else | |
| 574 *image_handle = IPC::PlatformFileForTransit(local_fd, false); | |
| 575 #elif defined(OS_POSIX) | 605 #elif defined(OS_POSIX) |
| 576 *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); | 606 *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); |
| 577 #else | 607 #else |
| 578 #error Not implemented. | 608 #error Not implemented. |
| 579 #endif | 609 #endif |
| 580 | 610 |
| 581 return resource.Release(); | 611 return resource.Release(); |
| 582 } | 612 } |
| 583 | 613 |
| 584 void PPB_ImageData_Proxy::OnHostMsgCreate(PP_Instance instance, | 614 void PPB_ImageData_Proxy::OnHostMsgCreatePlatform( |
| 585 int32_t format, | 615 PP_Instance instance, |
| 586 const PP_Size& size, | 616 int32_t format, |
| 587 PP_Bool init_to_zero, | 617 const PP_Size& size, |
| 588 HostResource* result, | 618 PP_Bool init_to_zero, |
| 589 std::string* image_data_desc, | 619 HostResource* result, |
| 590 ImageHandle* result_image_handle) { | 620 PP_ImageDataDesc* desc, |
| 591 PP_ImageDataDesc desc; | 621 ImageHandle* result_image_handle) { |
| 592 IPC::PlatformFileForTransit image_handle; | 622 IPC::PlatformFileForTransit image_handle; |
| 593 uint32_t byte_count; | 623 uint32_t byte_count; |
| 594 PP_Resource resource = | 624 PP_Resource resource = |
| 595 CreateImageData(instance, | 625 CreateImageData(instance, |
| 626 PPB_ImageData_Shared::PLATFORM, |
| 596 static_cast<PP_ImageDataFormat>(format), | 627 static_cast<PP_ImageDataFormat>(format), |
| 597 size, | 628 size, |
| 598 true /* init_to_zero */, | 629 true /* init_to_zero */, |
| 599 false /* is_nacl_plugin */, | 630 desc, &image_handle, &byte_count); |
| 600 &desc, &image_handle, &byte_count); | |
| 601 result->SetHostResource(instance, resource); | 631 result->SetHostResource(instance, resource); |
| 602 if (resource) { | 632 if (resource) { |
| 603 image_data_desc->resize(sizeof(PP_ImageDataDesc)); | |
| 604 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); | |
| 605 #if defined(TOOLKIT_GTK) | 633 #if defined(TOOLKIT_GTK) |
| 606 // On X Windows ImageHandle is a SysV shared memory key. | 634 // On X Windows ImageHandle is a SysV shared memory key. |
| 607 *result_image_handle = image_handle.fd; | 635 *result_image_handle = image_handle.fd; |
| 608 #else | 636 #else |
| 609 *result_image_handle = image_handle; | 637 *result_image_handle = image_handle; |
| 610 #endif | 638 #endif |
| 611 } else { | 639 } else { |
| 612 image_data_desc->clear(); | 640 *result_image_handle = PlatformImageData::NullHandle(); |
| 613 *result_image_handle = ImageData::NullHandle(); | |
| 614 } | 641 } |
| 615 } | 642 } |
| 616 | 643 |
| 617 void PPB_ImageData_Proxy::OnHostMsgCreateNaCl( | 644 void PPB_ImageData_Proxy::OnHostMsgCreateSimple( |
| 618 PP_Instance instance, | 645 PP_Instance instance, |
| 619 int32_t format, | 646 int32_t format, |
| 620 const PP_Size& size, | 647 const PP_Size& size, |
| 621 PP_Bool init_to_zero, | 648 PP_Bool init_to_zero, |
| 622 HostResource* result, | 649 HostResource* result, |
| 623 std::string* image_data_desc, | 650 PP_ImageDataDesc* desc, |
| 624 ppapi::proxy::SerializedHandle* result_image_handle) { | 651 ppapi::proxy::SerializedHandle* result_image_handle) { |
| 625 PP_ImageDataDesc desc; | |
| 626 IPC::PlatformFileForTransit image_handle; | 652 IPC::PlatformFileForTransit image_handle; |
| 627 uint32_t byte_count; | 653 uint32_t byte_count; |
| 628 PP_Resource resource = | 654 PP_Resource resource = |
| 629 CreateImageData(instance, | 655 CreateImageData(instance, |
| 656 PPB_ImageData_Shared::SIMPLE, |
| 630 static_cast<PP_ImageDataFormat>(format), | 657 static_cast<PP_ImageDataFormat>(format), |
| 631 size, | 658 size, |
| 632 true /* init_to_zero */, | 659 true /* init_to_zero */, |
| 633 true /* is_nacl_plugin */, | 660 desc, &image_handle, &byte_count); |
| 634 &desc, &image_handle, &byte_count); | |
| 635 | 661 |
| 636 result->SetHostResource(instance, resource); | 662 result->SetHostResource(instance, resource); |
| 637 if (resource) { | 663 if (resource) { |
| 638 image_data_desc->resize(sizeof(PP_ImageDataDesc)); | |
| 639 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); | |
| 640 result_image_handle->set_shmem(image_handle, byte_count); | 664 result_image_handle->set_shmem(image_handle, byte_count); |
| 641 } else { | 665 } else { |
| 642 image_data_desc->clear(); | |
| 643 result_image_handle->set_null_shmem(); | 666 result_image_handle->set_null_shmem(); |
| 644 } | 667 } |
| 645 } | 668 } |
| 646 #endif // !defined(OS_NACL) | 669 #endif // !defined(OS_NACL) |
| 647 | 670 |
| 648 void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData( | 671 void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData( |
| 649 const HostResource& old_image_data) { | 672 const HostResource& old_image_data) { |
| 650 PluginGlobals* plugin_globals = PluginGlobals::Get(); | 673 PluginGlobals* plugin_globals = PluginGlobals::Get(); |
| 651 if (!plugin_globals) | 674 if (!plugin_globals) |
| 652 return; // This may happen if the plugin is maliciously sending this | 675 return; // This may happen if the plugin is maliciously sending this |
| 653 // message to the renderer. | 676 // message to the renderer. |
| 654 | 677 |
| 655 EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data); | 678 EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data); |
| 656 if (enter.succeeded()) { | 679 if (enter.succeeded()) { |
| 657 ImageData* image_data = static_cast<ImageData*>(enter.object()); | 680 ImageData* image_data = static_cast<ImageData*>(enter.object()); |
| 658 ImageDataCache::GetInstance()->ImageDataUsable(image_data); | 681 ImageDataCache::GetInstance()->ImageDataUsable(image_data); |
| 659 } | 682 } |
| 660 | 683 |
| 661 // The renderer sent us a reference with the message. If the image data was | 684 // The renderer sent us a reference with the message. If the image data was |
| 662 // still cached in our process, the proxy still holds a reference so we can | 685 // still cached in our process, the proxy still holds a reference so we can |
| 663 // remove the one the renderer just sent is. If the proxy no longer holds a | 686 // remove the one the renderer just sent is. If the proxy no longer holds a |
| 664 // reference, we released everything and we should also release the one the | 687 // reference, we released everything and we should also release the one the |
| 665 // renderer just sent us. | 688 // renderer just sent us. |
| 666 dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource( | 689 dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource( |
| 667 API_ID_PPB_CORE, old_image_data)); | 690 API_ID_PPB_CORE, old_image_data)); |
| 668 } | 691 } |
| 669 | 692 |
| 670 } // namespace proxy | 693 } // namespace proxy |
| 671 } // namespace ppapi | 694 } // namespace ppapi |
| OLD | NEW |