// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppb_image_data_proxy.h"

#include <string.h>  // For memcpy

#include <map>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/proxy/enter_proxy.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/plugin_resource_tracker.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/thunk.h"

#if !defined(OS_NACL)
#include "skia/ext/platform_canvas.h"
#include "ui/surface/transport_dib.h"
#endif

using ppapi::thunk::PPB_ImageData_API;

namespace ppapi {
namespace proxy {

namespace {

// How ImageData re-use works
// --------------------------
//
// When animating plugins (like video), re-creating image datas for each frame
// and mapping the memory has a high overhead. So we try to re-use these when
// possible.
//
// 1. Plugin makes an asynchronous call that transfers an ImageData to the
//    implementation of some API.
// 2. Plugin frees its ImageData reference. If it doesn't do this we can't
//    re-use it.
// 3. When the last plugin ref of an ImageData is released, we don't actually
//    delete it. Instead we put it on a queue where we hold onto it in the
//    plugin process for a short period of time.
// 4. The API implementation that received the ImageData finishes using it.
//    Without our caching system it would get deleted at this point.
// 5. The proxy in the renderer will send NotifyUnusedImageData back to the
//    plugin process. We check if the given resource is in the queue and mark
//    it as usable.
// 6. When the plugin requests a new image data, we check our queue and if there
//    is a usable ImageData of the right size and format, we'll return it
//    instead of making a new one. It's important that caching is only requested
//    when the size is unlikely to change, so cache hits are high.
//
// Some notes:
//
//  - We only re-use image data when the plugin and host are rapidly exchanging
//    them and the size is likely to remain constant. It should be clear that
//    the plugin is promising that it's done with the image.
//
//  - Theoretically we could re-use them in other cases but the lifetime
//    becomes more difficult to manage. The plugin could have used an ImageData
//    in an arbitrary number of queued up PaintImageData calls which we would
//    have to check.
//
//  - If a flush takes a long time or there are many released image datas
//    accumulating in our queue such that some are deleted, we will have
//    released our reference by the time the renderer notifies us of an unused
//    image data. In this case we just give up.
//
//  - We maintain a per-instance cache. Some pages have many instances of
//    Flash, for example, each of a different size. If they're all animating we
//    want each to get its own image data re-use.
//
//  - We generate new resource IDs when re-use happens to try to avoid weird
//    problems if the plugin messes up its refcounting.

// Keep a cache entry for this many seconds before expiring it. We get an entry
// back from the renderer after an ImageData is swapped out, so it means the
// plugin has to be painting at least two frames for this time interval to
// get caching.
static const int kMaxAgeSeconds = 2;

// ImageDataCacheEntry ---------------------------------------------------------

struct ImageDataCacheEntry {
  ImageDataCacheEntry() : usable(false) {}
  explicit ImageDataCacheEntry(ImageData* i)
      : added_time(base::TimeTicks::Now()), usable(false), image(i) {}

  base::TimeTicks added_time;

  // Set to true when the renderer tells us that it's OK to re-use this iamge.
  bool usable;

  scoped_refptr<ImageData> image;
};

// ImageDataInstanceCache ------------------------------------------------------

// Per-instance cache of image datas.
class ImageDataInstanceCache {
 public:
  ImageDataInstanceCache() : next_insertion_point_(0) {}

  // These functions have the same spec as the ones in ImageDataCache.
  scoped_refptr<ImageData> Get(PPB_ImageData_Shared::ImageDataType type,
                               int width, int height,
                               PP_ImageDataFormat format);
  void Add(ImageData* image_data);
  void ImageDataUsable(ImageData* image_data);

  // Expires old entries. Returns true if there are still entries in the list,
  // false if this instance cache is now empty.
  bool ExpireEntries();

 private:
  void IncrementInsertionPoint();

  // We'll store this many ImageDatas per instance.
  static const size_t kCacheSize = 2;

  ImageDataCacheEntry images_[kCacheSize];

  // Index into cache where the next item will go.
  size_t next_insertion_point_;
};

scoped_refptr<ImageData> ImageDataInstanceCache::Get(
    PPB_ImageData_Shared::ImageDataType type,
    int width, int height,
    PP_ImageDataFormat format) {
  // Just do a brute-force search since the cache is so small.
  for (size_t i = 0; i < kCacheSize; i++) {
    if (!images_[i].usable)
      continue;
    if (images_[i].image->type() != type)
      continue;
    const PP_ImageDataDesc& desc = images_[i].image->desc();
    if (desc.format == format &&
        desc.size.width == width && desc.size.height == height) {
      scoped_refptr<ImageData> ret(images_[i].image);
      images_[i] = ImageDataCacheEntry();

      // Since we just removed an item, this entry is the best place to insert
      // a subsequent one.
      next_insertion_point_ = i;
      return ret;
    }
  }
  return scoped_refptr<ImageData>();
}

void ImageDataInstanceCache::Add(ImageData* image_data) {
  images_[next_insertion_point_] = ImageDataCacheEntry(image_data);
  IncrementInsertionPoint();
}

void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) {
  for (size_t i = 0; i < kCacheSize; i++) {
    if (images_[i].image.get() == image_data) {
      images_[i].usable = true;

      // This test is important. The renderer doesn't guarantee how many image
      // datas it has or when it notifies us when one is usable. Its possible
      // to get into situations where it's always telling us the old one is
      // usable, and then the older one immediately gets expired. Therefore,
      // if the next insertion would overwrite this now-usable entry, make the
      // next insertion overwrite some other entry to avoid the replacement.
      if (next_insertion_point_ == i)
        IncrementInsertionPoint();
      return;
    }
  }
}

bool ImageDataInstanceCache::ExpireEntries() {
  base::TimeTicks threshold_time =
      base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds);

  bool has_entry = false;
  for (size_t i = 0; i < kCacheSize; i++) {
    if (images_[i].image.get()) {
      // Entry present.
      if (images_[i].added_time <= threshold_time) {
        // Found an entry to expire.
        images_[i] = ImageDataCacheEntry();
        next_insertion_point_ = i;
      } else {
        // Found an entry that we're keeping.
        has_entry = true;
      }
    }
  }
  return has_entry;
}

void ImageDataInstanceCache::IncrementInsertionPoint() {
  // Go to the next location, wrapping around to get LRU.
  next_insertion_point_++;
  if (next_insertion_point_ >= kCacheSize)
    next_insertion_point_ = 0;
}

// ImageDataCache --------------------------------------------------------------

class ImageDataCache {
 public:
  ImageDataCache() : weak_factory_(this) {}
  ~ImageDataCache() {}

  static ImageDataCache* GetInstance();

  // Retrieves an image data from the cache of the specified type, size and
  // format if one exists. If one doesn't exist, this will return a null refptr.
  scoped_refptr<ImageData> Get(PP_Instance instance,
                               PPB_ImageData_Shared::ImageDataType type,
                               int width, int height,
                               PP_ImageDataFormat format);

  // Adds the given image data to the cache. There should be no plugin
  // references to it. This may delete an older item from the cache.
  void Add(ImageData* image_data);

  // Notification from the renderer that the given image data is usable.
  void ImageDataUsable(ImageData* image_data);

  void DidDeleteInstance(PP_Instance instance);

 private:
  friend struct base::LeakySingletonTraits<ImageDataCache>;

  // Timer callback to expire entries for the given instance.
  void OnTimer(PP_Instance instance);

  typedef std::map<PP_Instance, ImageDataInstanceCache> CacheMap;
  CacheMap cache_;

  // This class does timer calls and we don't want to run these outside of the
  // scope of the object. Technically, since this class is a leaked static,
  // this will never happen and this factory is unnecessary. However, it's
  // probably better not to make assumptions about the lifetime of this class.
  base::WeakPtrFactory<ImageDataCache> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ImageDataCache);
};

// static
ImageDataCache* ImageDataCache::GetInstance() {
  return base::Singleton<ImageDataCache,
                         base::LeakySingletonTraits<ImageDataCache>>::get();
}

scoped_refptr<ImageData> ImageDataCache::Get(
    PP_Instance instance,
    PPB_ImageData_Shared::ImageDataType type,
    int width, int height,
    PP_ImageDataFormat format) {
  CacheMap::iterator found = cache_.find(instance);
  if (found == cache_.end())
    return scoped_refptr<ImageData>();
  return found->second.Get(type, width, height, format);
}

void ImageDataCache::Add(ImageData* image_data) {
  cache_[image_data->pp_instance()].Add(image_data);

  // Schedule a timer to invalidate this entry.
  PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostDelayedTask(
      FROM_HERE,
      RunWhileLocked(base::Bind(&ImageDataCache::OnTimer,
                                weak_factory_.GetWeakPtr(),
                                image_data->pp_instance())),
      base::TimeDelta::FromSeconds(kMaxAgeSeconds));
}

void ImageDataCache::ImageDataUsable(ImageData* image_data) {
  CacheMap::iterator found = cache_.find(image_data->pp_instance());
  if (found != cache_.end())
    found->second.ImageDataUsable(image_data);
}

void ImageDataCache::DidDeleteInstance(PP_Instance instance) {
  cache_.erase(instance);
}

void ImageDataCache::OnTimer(PP_Instance instance) {
  CacheMap::iterator found = cache_.find(instance);
  if (found == cache_.end())
    return;
  if (!found->second.ExpireEntries()) {
    // There are no more entries for this instance, remove it from the cache.
    cache_.erase(found);
  }
}

}  // namespace

// ImageData -------------------------------------------------------------------

ImageData::ImageData(const HostResource& resource,
                     PPB_ImageData_Shared::ImageDataType type,
                     const PP_ImageDataDesc& desc)
    : Resource(OBJECT_IS_PROXY, resource),
      type_(type),
      desc_(desc),
      is_candidate_for_reuse_(false) {
}

ImageData::~ImageData() {
}

PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
  return this;
}

void ImageData::LastPluginRefWasDeleted() {
  // The plugin no longer needs this ImageData, add it to our cache if it's
  // been used in a ReplaceContents. These are the ImageDatas that the renderer
  // will send back ImageDataUsable messages for.
  if (is_candidate_for_reuse_)
    ImageDataCache::GetInstance()->Add(this);
}

void ImageData::InstanceWasDeleted() {
  ImageDataCache::GetInstance()->DidDeleteInstance(pp_instance());
}

PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
  memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
  return PP_TRUE;
}

int32_t ImageData::GetSharedMemory(base::SharedMemory** /* shm */,
                                   uint32_t* /* byte_count */) {
  // Not supported in the proxy (this method is for actually implementing the
  // proxy in the host).
  return PP_ERROR_NOACCESS;
}

void ImageData::SetIsCandidateForReuse() {
  is_candidate_for_reuse_ = true;
}

void ImageData::RecycleToPlugin(bool zero_contents) {
  is_candidate_for_reuse_ = false;
  if (zero_contents) {
    void* data = Map();
    memset(data, 0, desc_.stride * desc_.size.height);
    Unmap();
  }
}

// PlatformImageData -----------------------------------------------------------

#if !defined(OS_NACL)
PlatformImageData::PlatformImageData(const HostResource& resource,
                                     const PP_ImageDataDesc& desc,
                                     ImageHandle handle)
    : ImageData(resource, PPB_ImageData_Shared::PLATFORM, desc) {
#if defined(OS_WIN)
  transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
#else
  transport_dib_.reset(TransportDIB::Map(handle));
#endif  // defined(OS_WIN)
}

PlatformImageData::~PlatformImageData() {
}

void* PlatformImageData::Map() {
  if (!mapped_canvas_.get()) {
    if (!transport_dib_.get())
      return NULL;

    const bool is_opaque = false;
    mapped_canvas_ = transport_dib_->GetPlatformCanvas(
        desc_.size.width, desc_.size.height, is_opaque);
    if (!mapped_canvas_.get())
      return NULL;
  }
  SkPixmap pixmap;
  skia::GetWritablePixels(mapped_canvas_.get(), &pixmap);
  return pixmap.writable_addr();
}

void PlatformImageData::Unmap() {
  // TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't
  // possible since deleting the TransportDIB also frees all the handles.
  // We need to add a method to TransportDIB to release the handles.
}

SkCanvas* PlatformImageData::GetCanvas() {
  return mapped_canvas_.get();
}

// static
ImageHandle PlatformImageData::NullHandle() {
  return ImageHandle();
}
#endif  // !defined(OS_NACL)

// SimpleImageData -------------------------------------------------------------

SimpleImageData::SimpleImageData(const HostResource& resource,
                                 const PP_ImageDataDesc& desc,
                                 const base::SharedMemoryHandle& handle)
    : ImageData(resource, PPB_ImageData_Shared::SIMPLE, desc),
      shm_(handle, false /* read_only */),
      size_(desc.size.width * desc.size.height * 4),
      map_count_(0) {
}

SimpleImageData::~SimpleImageData() {
}

void* SimpleImageData::Map() {
  if (map_count_++ == 0)
    shm_.Map(size_);
  return shm_.memory();
}

void SimpleImageData::Unmap() {
  if (--map_count_ == 0)
    shm_.Unmap();
}

SkCanvas* SimpleImageData::GetCanvas() {
  return NULL;  // No canvas available.
}

// PPB_ImageData_Proxy ---------------------------------------------------------

PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher)
    : InterfaceProxy(dispatcher) {
}

PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
}

// static
PP_Resource PPB_ImageData_Proxy::CreateProxyResource(
    PP_Instance instance,
    PPB_ImageData_Shared::ImageDataType type,
    PP_ImageDataFormat format,
    const PP_Size& size,
    PP_Bool init_to_zero) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (!dispatcher)
    return 0;

  // Check the cache.
  scoped_refptr<ImageData> cached_image_data =
      ImageDataCache::GetInstance()->Get(instance, type,
                                         size.width, size.height, format);
  if (cached_image_data.get()) {
    // We have one we can re-use rather than allocating a new one.
    cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero));
    return cached_image_data->GetReference();
  }

  HostResource result;
  PP_ImageDataDesc desc;
  switch (type) {
    case PPB_ImageData_Shared::SIMPLE: {
      ppapi::proxy::SerializedHandle image_handle_wrapper;
      dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateSimple(
          kApiID, instance, format, size, init_to_zero,
          &result, &desc, &image_handle_wrapper));
      if (image_handle_wrapper.is_shmem()) {
        base::SharedMemoryHandle image_handle = image_handle_wrapper.shmem();
        if (!result.is_null()) {
          return
              (new SimpleImageData(result, desc, image_handle))->GetReference();
        }
      }
      break;
    }
    case PPB_ImageData_Shared::PLATFORM: {
#if !defined(OS_NACL)
      ImageHandle image_handle = PlatformImageData::NullHandle();
      dispatcher->Send(new PpapiHostMsg_PPBImageData_CreatePlatform(
          kApiID, instance, format, size, init_to_zero,
          &result, &desc, &image_handle));
      if (!result.is_null()) {
        return
            (new PlatformImageData(result, desc, image_handle))->GetReference();
      }
#else
      // PlatformImageData shouldn't be created in untrusted code.
      NOTREACHED();
#endif
      break;
    }
  }

  return 0;
}

bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
#if !defined(OS_NACL)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreatePlatform,
                        OnHostMsgCreatePlatform)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateSimple,
                        OnHostMsgCreateSimple)
#endif
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBImageData_NotifyUnusedImageData,
                        OnPluginMsgNotifyUnusedImageData)

    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

#if !defined(OS_NACL)
// static
PP_Resource PPB_ImageData_Proxy::CreateImageData(
    PP_Instance instance,
    PPB_ImageData_Shared::ImageDataType type,
    PP_ImageDataFormat format,
    const PP_Size& size,
    bool init_to_zero,
    PP_ImageDataDesc* desc,
    base::SharedMemoryHandle* image_handle,
    uint32_t* byte_count) {
  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
  if (!dispatcher)
    return 0;

  thunk::EnterResourceCreation enter(instance);
  if (enter.failed())
    return 0;

  PP_Bool pp_init_to_zero = init_to_zero ? PP_TRUE : PP_FALSE;
  PP_Resource pp_resource = 0;
  switch (type) {
    case PPB_ImageData_Shared::SIMPLE: {
      pp_resource = enter.functions()->CreateImageDataSimple(
          instance, format, &size, pp_init_to_zero);
      break;
    }
    case PPB_ImageData_Shared::PLATFORM: {
      pp_resource = enter.functions()->CreateImageData(
          instance, format, &size, pp_init_to_zero);
      break;
    }
  }

  if (!pp_resource)
    return 0;

  ppapi::ScopedPPResource resource(ppapi::ScopedPPResource::PassRef(),
                                   pp_resource);

  thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource.get(),
                                                               false);
  if (enter_resource.object()->Describe(desc) != PP_TRUE) {
    DVLOG(1) << "CreateImageData failed: could not Describe";
    return 0;
  }

  base::SharedMemory* local_shm;
  if (enter_resource.object()->GetSharedMemory(&local_shm, byte_count) !=
      PP_OK) {
    DVLOG(1) << "CreateImageData failed: could not GetSharedMemory";
    return 0;
  }

  *image_handle =
      dispatcher->ShareSharedMemoryHandleWithRemote(local_shm->handle());
  return resource.Release();
}

void PPB_ImageData_Proxy::OnHostMsgCreatePlatform(
    PP_Instance instance,
    int32_t format,
    const PP_Size& size,
    PP_Bool init_to_zero,
    HostResource* result,
    PP_ImageDataDesc* desc,
    ImageHandle* result_image_handle) {
  // Clear |desc| so we don't send uninitialized memory to the plugin.
  // https://crbug.com/391023.
  *desc = PP_ImageDataDesc();
  base::SharedMemoryHandle image_handle;
  uint32_t byte_count;
  PP_Resource resource =
      CreateImageData(instance,
                      PPB_ImageData_Shared::PLATFORM,
                      static_cast<PP_ImageDataFormat>(format),
                      size,
                      true /* init_to_zero */,
                      desc, &image_handle, &byte_count);
  result->SetHostResource(instance, resource);
  *result_image_handle =
      resource ? image_handle : PlatformImageData::NullHandle();
}

void PPB_ImageData_Proxy::OnHostMsgCreateSimple(
    PP_Instance instance,
    int32_t format,
    const PP_Size& size,
    PP_Bool init_to_zero,
    HostResource* result,
    PP_ImageDataDesc* desc,
    ppapi::proxy::SerializedHandle* result_image_handle) {
  // Clear |desc| so we don't send uninitialized memory to the plugin.
  // https://crbug.com/391023.
  *desc = PP_ImageDataDesc();
  base::SharedMemoryHandle image_handle;
  uint32_t byte_count;
  PP_Resource resource =
      CreateImageData(instance,
                      PPB_ImageData_Shared::SIMPLE,
                      static_cast<PP_ImageDataFormat>(format),
                      size,
                      true /* init_to_zero */,
                      desc, &image_handle, &byte_count);

  result->SetHostResource(instance, resource);
  if (resource) {
    result_image_handle->set_shmem(image_handle, byte_count);
  } else {
    result_image_handle->set_null_shmem();
  }
}
#endif  // !defined(OS_NACL)

void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData(
    const HostResource& old_image_data) {
  PluginGlobals* plugin_globals = PluginGlobals::Get();
  if (!plugin_globals) {
    return;  // This may happen if the plugin is maliciously sending this
             // message to the renderer.
  }

  EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data);
  if (enter.succeeded()) {
    ImageData* image_data = static_cast<ImageData*>(enter.object());
    ImageDataCache::GetInstance()->ImageDataUsable(image_data);
  }

  // The renderer sent us a reference with the message. If the image data was
  // still cached in our process, the proxy still holds a reference so we can
  // remove the one the renderer just sent is. If the proxy no longer holds a
  // reference, we released everything and we should also release the one the
  // renderer just sent us.
  dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
      API_ID_PPB_CORE, old_image_data));
}

}  // namespace proxy
}  // namespace ppapi
