// Copyright (c) 2013 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 "content/renderer/media/midi_message_filter.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/media/midi_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/ipc_logging.h"

using media::MIDIPortInfoList;
using base::AutoLock;

// The maximum number of bytes which we're allowed to send to the browser
// before getting acknowledgement back from the browser that they've been
// successfully sent.
static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024;  // 10 MB.

namespace content {

MIDIMessageFilter::MIDIMessageFilter(
    const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
    : channel_(NULL),
      io_message_loop_(io_message_loop),
      main_message_loop_(base::MessageLoopProxy::current()),
      next_available_id_(0),
      unacknowledged_bytes_sent_(0) {
}

MIDIMessageFilter::~MIDIMessageFilter() {}

void MIDIMessageFilter::Send(IPC::Message* message) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  if (!channel_) {
    delete message;
  } else {
    channel_->Send(message);
  }
}

bool MIDIMessageFilter::OnMessageReceived(const IPC::Message& message) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(MIDIMessageFilter, message)
    IPC_MESSAGE_HANDLER(MIDIMsg_SessionStarted, OnSessionStarted)
    IPC_MESSAGE_HANDLER(MIDIMsg_DataReceived, OnDataReceived)
    IPC_MESSAGE_HANDLER(MIDIMsg_AcknowledgeSentData, OnAcknowledgeSentData)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void MIDIMessageFilter::OnFilterAdded(IPC::Channel* channel) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  channel_ = channel;
}

void MIDIMessageFilter::OnFilterRemoved() {
  DCHECK(io_message_loop_->BelongsToCurrentThread());

  // Once removed, a filter will not be used again.  At this time all
  // delegates must be notified so they release their reference.
  OnChannelClosing();
}

void MIDIMessageFilter::OnChannelClosing() {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  channel_ = NULL;
}

void MIDIMessageFilter::StartSession(WebKit::WebMIDIAccessorClient* client) {
  // Generate and keep track of a "client id" which is sent to the browser
  // to ask permission to talk to MIDI hardware.
  // This id is handed back when we receive the answer in OnAccessApproved().
  if (clients_.find(client) == clients_.end()) {
    int client_id = next_available_id_++;
    clients_[client] = client_id;

    io_message_loop_->PostTask(FROM_HERE,
        base::Bind(&MIDIMessageFilter::StartSessionOnIOThread, this,
                   client_id));
  }
}

void MIDIMessageFilter::StartSessionOnIOThread(int client_id) {
  Send(new MIDIHostMsg_StartSession(client_id));
}

void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
  ClientsMap::iterator i = clients_.find(client);
  if (i != clients_.end())
    clients_.erase(i);
}

// Received from browser.

void MIDIMessageFilter::OnSessionStarted(
    int client_id,
    bool success,
    MIDIPortInfoList inputs,
    MIDIPortInfoList outputs) {
  // Handle on the main JS thread.
  main_message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&MIDIMessageFilter::HandleSessionStarted, this,
                 client_id, success, inputs, outputs));
}

void MIDIMessageFilter::HandleSessionStarted(
    int client_id,
    bool success,
    MIDIPortInfoList inputs,
    MIDIPortInfoList outputs) {
  WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
  if (!client)
    return;

  if (success) {
    // Add the client's input and output ports.
    for (size_t i = 0; i < inputs.size(); ++i) {
      client->didAddInputPort(
          UTF8ToUTF16(inputs[i].id),
          UTF8ToUTF16(inputs[i].manufacturer),
          UTF8ToUTF16(inputs[i].name),
          UTF8ToUTF16(inputs[i].version));
    }

    for (size_t i = 0; i < outputs.size(); ++i) {
      client->didAddOutputPort(
          UTF8ToUTF16(outputs[i].id),
          UTF8ToUTF16(outputs[i].manufacturer),
          UTF8ToUTF16(outputs[i].name),
          UTF8ToUTF16(outputs[i].version));
    }
  }
  // TODO(toyoshim): Reports device initialization failure to JavaScript as
  // "NotSupportedError" or something when |success| is false.
  // http://crbug.com/260315
  client->didStartSession();
}

WebKit::WebMIDIAccessorClient*
MIDIMessageFilter::GetClientFromId(int client_id) {
  // Iterating like this seems inefficient, but in practice there generally
  // will be very few clients (usually one).  Additionally, this lookup
  // usually happens one time during page load. So the performance hit is
  // negligible.
  for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
    if ((*i).second == client_id)
      return (*i).first;
  }
  return NULL;
}

void MIDIMessageFilter::OnDataReceived(int port,
                                       const std::vector<uint8>& data,
                                       double timestamp) {
  TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");

  main_message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
                 port, data, timestamp));
}

void MIDIMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) {
  DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
  if (unacknowledged_bytes_sent_ >= bytes_sent)
    unacknowledged_bytes_sent_ -= bytes_sent;
}

void MIDIMessageFilter::HandleDataReceived(int port,
                                           const std::vector<uint8>& data,
                                           double timestamp) {
  TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");

#if defined(OS_ANDROID)
  // TODO(crogers): figure out why data() method does not compile on Android.
  NOTIMPLEMENTED();
#else
  for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
    (*i).first->didReceiveMIDIData(port, data.data(), data.size(), timestamp);
#endif
}

void MIDIMessageFilter::SendMIDIData(int port,
                                     const uint8* data,
                                     size_t length,
                                     double timestamp) {
  if (length > kMaxUnacknowledgedBytesSent) {
    // TODO(crogers): buffer up the data to send at a later time.
    // For now we're just dropping these bytes on the floor.
    return;
  }

  std::vector<uint8> v(data, data + length);
  io_message_loop_->PostTask(FROM_HERE,
      base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
                 port, v, timestamp));
}

void MIDIMessageFilter::SendMIDIDataOnIOThread(int port,
                                               const std::vector<uint8>& data,
                                               double timestamp) {
  size_t n = data.size();
  if (n > kMaxUnacknowledgedBytesSent ||
      unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent ||
      n + unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent) {
    // TODO(crogers): buffer up the data to send at a later time.
    // For now we're just dropping these bytes on the floor.
    return;
  }

  unacknowledged_bytes_sent_ += n;

  // Send to the browser.
  Send(new MIDIHostMsg_SendData(port, data, timestamp));
}

}  // namespace content
