// 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/device_enumeration_resource_helper.h"

#include <stddef.h>

#include <memory>

#include "base/bind.h"
#include "base/logging.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "ppapi/c/pp_array_output.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/dispatch_reply_message.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/shared_impl/array_writer.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/ppb_device_ref_shared.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/tracked_callback.h"

namespace ppapi {
namespace proxy {

DeviceEnumerationResourceHelper::DeviceEnumerationResourceHelper(
    PluginResource* owner)
    : owner_(owner),
      pending_enumerate_devices_(false),
      monitor_callback_id_(0),
      monitor_user_data_(NULL) {
}

DeviceEnumerationResourceHelper::~DeviceEnumerationResourceHelper() {
}

int32_t DeviceEnumerationResourceHelper::EnumerateDevices(
    const PP_ArrayOutput& output,
    scoped_refptr<TrackedCallback> callback) {
  if (pending_enumerate_devices_)
    return PP_ERROR_INPROGRESS;

  pending_enumerate_devices_ = true;
  PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg;
  owner_->Call<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
      PluginResource::RENDERER, msg,
      base::Bind(
          &DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply,
          AsWeakPtr(), output, callback));
  return PP_OK_COMPLETIONPENDING;
}

int32_t DeviceEnumerationResourceHelper::EnumerateDevicesSync(
    const PP_ArrayOutput& output) {
  std::vector<DeviceRefData> devices;
  int32_t result =
      owner_->SyncCall<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
          PluginResource::RENDERER,
          PpapiHostMsg_DeviceEnumeration_EnumerateDevices(),
          &devices);

  if (result == PP_OK)
    result = WriteToArrayOutput(devices, output);

  return result;
}

int32_t DeviceEnumerationResourceHelper::MonitorDeviceChange(
    PP_MonitorDeviceChangeCallback callback,
    void* user_data) {
  monitor_callback_id_++;
  monitor_user_data_ = user_data;
  if (callback) {
    monitor_callback_.reset(
        ThreadAwareCallback<PP_MonitorDeviceChangeCallback>::Create(callback));
    if (!monitor_callback_.get())
      return PP_ERROR_NO_MESSAGE_LOOP;

    owner_->Post(PluginResource::RENDERER,
                 PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange(
                     monitor_callback_id_));
  } else {
    monitor_callback_.reset(NULL);

    owner_->Post(PluginResource::RENDERER,
                 PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange());
  }
  return PP_OK;
}

bool DeviceEnumerationResourceHelper::HandleReply(
    const ResourceMessageReplyParams& params,
    const IPC::Message& msg) {
  PPAPI_BEGIN_MESSAGE_MAP(DeviceEnumerationResourceHelper, msg)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange,
        OnPluginMsgNotifyDeviceChange)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(return false)
  PPAPI_END_MESSAGE_MAP()

  return true;
}

void DeviceEnumerationResourceHelper::LastPluginRefWasDeleted() {
  // Make sure that no further notifications are sent to the plugin.
  monitor_callback_id_++;
  monitor_callback_.reset(NULL);
  monitor_user_data_ = NULL;

  // There is no need to do anything with pending callback of
  // EnumerateDevices(), because OnPluginMsgEnumerateDevicesReply*() will handle
  // that properly.
}

void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply(
    const PP_ArrayOutput& output,
    scoped_refptr<TrackedCallback> callback,
    const ResourceMessageReplyParams& params,
    const std::vector<DeviceRefData>& devices) {
  pending_enumerate_devices_ = false;

  // We shouldn't access |output| if the callback has been called, which is
  // possible if the last plugin reference to the corresponding resource has
  // gone away, and the callback has been aborted.
  if (!TrackedCallback::IsPending(callback))
    return;

  int32_t result = params.result();
  if (result == PP_OK)
    result = WriteToArrayOutput(devices, output);

  callback->Run(result);
}

void DeviceEnumerationResourceHelper::OnPluginMsgNotifyDeviceChange(
    const ResourceMessageReplyParams& /* params */,
    uint32_t callback_id,
    const std::vector<DeviceRefData>& devices) {
  if (monitor_callback_id_ != callback_id) {
    // A new callback or NULL has been set.
    return;
  }

  CHECK(monitor_callback_.get());

  std::unique_ptr<PP_Resource[]> elements;
  uint32_t size = static_cast<uint32_t>(devices.size());
  if (size > 0) {
    elements.reset(new PP_Resource[size]);
    for (size_t index = 0; index < size; ++index) {
      PPB_DeviceRef_Shared* device_object = new PPB_DeviceRef_Shared(
          OBJECT_IS_PROXY, owner_->pp_instance(), devices[index]);
      elements[index] = device_object->GetReference();
    }
  }

  monitor_callback_->RunOnTargetThread(monitor_user_data_, size,
                                       elements.get());
  for (size_t index = 0; index < size; ++index)
    PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(elements[index]);
}

int32_t DeviceEnumerationResourceHelper::WriteToArrayOutput(
    const std::vector<DeviceRefData>& devices,
    const PP_ArrayOutput& output) {
  ArrayWriter writer(output);
  if (!writer.is_valid())
    return PP_ERROR_BADARGUMENT;

  std::vector<scoped_refptr<Resource> > device_resources;
  for (size_t i = 0; i < devices.size(); ++i) {
    device_resources.push_back(new PPB_DeviceRef_Shared(
        OBJECT_IS_PROXY, owner_->pp_instance(), devices[i]));
  }
  if (!writer.StoreResourceVector(device_resources))
    return PP_ERROR_FAILED;

  return PP_OK;
}

}  // namespace proxy
}  // namespace ppapi
