// 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/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() : added_time(), usable(false), image() {}
  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.
  const static int kCacheSize = 2;

  ImageDataCacheEntry images_[kCacheSize];

  // Index into cache where the next item will go.
  int 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 (int 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 (int 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 (int 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 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 Singleton<ImageDataCache,
                   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.
  base::MessageLoop::current()->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(int* /* handle */,
                                   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()) {
    mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width,
                                                           desc_.size.height));
    if (!mapped_canvas_.get())
      return NULL;
  }
  const SkBitmap& bitmap =
      skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);

  bitmap.lockPixels();
  return bitmap.getAddr(0, 0);
}

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::GetPlatformCanvas() {
  return mapped_canvas_.get();
}

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

// static
ImageHandle PlatformImageData::NullHandle() {
#if defined(OS_WIN)
  return NULL;
#else
  return ImageHandle();
#endif
}

ImageHandle PlatformImageData::HandleFromInt(int32_t i) {
#if defined(OS_WIN)
    return reinterpret_cast<ImageHandle>(i);
#else
    return ImageHandle(i, false);
#endif
}
#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::GetPlatformCanvas() {
  return NULL;  // No canvas available.
}

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,
    IPC::PlatformFileForTransit* 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;
  }

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

#if defined(OS_WIN)
  *image_handle = dispatcher->ShareHandleWithRemote(
      reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false);
#elif defined(OS_POSIX)
  *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
#else
  #error Not implemented.
#endif

  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 unitialized memory to the plugin.
  // https://crbug.com/391023.
  *desc = PP_ImageDataDesc();
  IPC::PlatformFileForTransit 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);
  if (resource) {
    *result_image_handle = image_handle;
  } else {
    *result_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 unitialized memory to the plugin.
  // https://crbug.com/391023.
  *desc = PP_ImageDataDesc();
  IPC::PlatformFileForTransit 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
