// Copyright (c) 2009 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 "chrome/plugin/plugin_channel_base.h"

#include <stack>

#include "base/auto_reset.h"
#include "base/hash_tables.h"
#include "base/lazy_instance.h"
#include "chrome/common/child_process.h"
#include "ipc/ipc_sync_message.h"

#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
#endif

typedef base::hash_map<std::string, scoped_refptr<PluginChannelBase> >
    PluginChannelMap;

static PluginChannelMap g_plugin_channels_;

static base::LazyInstance<std::stack<scoped_refptr<PluginChannelBase> > >
    lazy_plugin_channel_stack_(base::LINKER_INITIALIZED);

PluginChannelBase* PluginChannelBase::GetChannel(
    const std::string& channel_name, IPC::Channel::Mode mode,
    PluginChannelFactory factory, MessageLoop* ipc_message_loop,
    bool create_pipe_now) {
  scoped_refptr<PluginChannelBase> channel;

  PluginChannelMap::const_iterator iter = g_plugin_channels_.find(channel_name);
  if (iter == g_plugin_channels_.end()) {
    channel = factory();
  } else {
    channel = iter->second;
  }

  DCHECK(channel != NULL);

  if (!channel->channel_valid()) {
    channel->channel_name_ = channel_name;
    channel->mode_ = mode;
    if (channel->Init(ipc_message_loop, create_pipe_now)) {
      g_plugin_channels_[channel_name] = channel;
    } else {
      channel = NULL;
    }
  }

  return channel;
}

void PluginChannelBase::Broadcast(IPC::Message* message) {
  for (PluginChannelMap::iterator iter = g_plugin_channels_.begin();
       iter != g_plugin_channels_.end();
       ++iter) {
    iter->second->Send(new IPC::Message(*message));
  }
  delete message;
}

PluginChannelBase::PluginChannelBase()
    : plugin_count_(0),
      peer_pid_(0),
      in_remove_route_(false),
      channel_valid_(false),
      in_sync_dispatch_(0),
      send_unblocking_only_during_sync_dispatch_(false) {
}

PluginChannelBase::~PluginChannelBase() {
}

PluginChannelBase* PluginChannelBase::GetCurrentChannel() {
  return lazy_plugin_channel_stack_.Pointer()->top();
}

void PluginChannelBase::CleanupChannels() {
  // Make a copy of the references as we can't iterate the map since items will
  // be removed from it as we clean them up.
  std::vector<scoped_refptr<PluginChannelBase> > channels;
  for (PluginChannelMap::const_iterator iter = g_plugin_channels_.begin();
       iter != g_plugin_channels_.end();
       ++iter) {
    channels.push_back(iter->second);
  }

  for (size_t i = 0; i < channels.size(); ++i)
    channels[i]->CleanUp();

  // This will clean up channels added to the map for which subsequent
  // AddRoute wasn't called
  g_plugin_channels_.clear();
}

bool PluginChannelBase::Init(MessageLoop* ipc_message_loop,
                             bool create_pipe_now) {
  channel_.reset(new IPC::SyncChannel(
      channel_name_, mode_, this, NULL, ipc_message_loop, create_pipe_now,
      ChildProcess::current()->GetShutDownEvent()));
  channel_valid_ = true;
  return true;
}

bool PluginChannelBase::Send(IPC::Message* message) {
  if (!channel_.get()) {
    delete message;
    return false;
  }

  if (send_unblocking_only_during_sync_dispatch_ && in_sync_dispatch_ == 0 &&
      message->is_sync()) {
    message->set_unblock(false);
  }

  return channel_->Send(message);
}

int PluginChannelBase::Count() {
  return static_cast<int>(g_plugin_channels_.size());
}

void PluginChannelBase::OnMessageReceived(const IPC::Message& message) {
  // This call might cause us to be deleted, so keep an extra reference to
  // ourself so that we can send the reply and decrement back in_dispatch_.
  lazy_plugin_channel_stack_.Pointer()->push(
      scoped_refptr<PluginChannelBase>(this));

  if (message.is_sync())
    in_sync_dispatch_++;
  if (message.routing_id() == MSG_ROUTING_CONTROL) {
    OnControlMessageReceived(message);
  } else {
    bool routed = router_.RouteMessage(message);
    if (!routed && message.is_sync()) {
      // The listener has gone away, so we must respond or else the caller will
      // hang waiting for a reply.
      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
      reply->set_reply_error();
      Send(reply);
    }
  }
  if (message.is_sync())
    in_sync_dispatch_--;

  lazy_plugin_channel_stack_.Pointer()->pop();
}

void PluginChannelBase::OnChannelConnected(int32 peer_pid) {
  peer_pid_ = peer_pid;
}

void PluginChannelBase::AddRoute(int route_id,
                                 IPC::Channel::Listener* listener,
                                 bool npobject) {
  if (npobject) {
    npobject_listeners_[route_id] = listener;
  } else {
    plugin_count_++;
  }

  router_.AddRoute(route_id, listener);
}

void PluginChannelBase::RemoveRoute(int route_id) {
  router_.RemoveRoute(route_id);

  ListenerMap::iterator iter = npobject_listeners_.find(route_id);
  if (iter != npobject_listeners_.end()) {
    // This was an NPObject proxy or stub, it's not involved in the refcounting.

    // If this RemoveRoute call from the NPObject is a result of us calling
    // OnChannelError below, don't call erase() here because that'll corrupt
    // the iterator below.
    if (in_remove_route_) {
      iter->second = NULL;
    } else {
      npobject_listeners_.erase(iter);
    }

    return;
  }

  plugin_count_--;
  DCHECK(plugin_count_ >= 0);

  if (!plugin_count_) {
    AutoReset auto_reset_in_remove_route(&in_remove_route_, true);
    for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin();
         npobj_iter != npobject_listeners_.end(); ++npobj_iter) {
      if (npobj_iter->second)
        npobj_iter->second->OnChannelError();
    }

    for (PluginChannelMap::iterator iter = g_plugin_channels_.begin();
         iter != g_plugin_channels_.end(); ++iter) {
      if (iter->second == this) {
#if defined(OS_POSIX)
        if (channel_valid()) {
          IPC::RemoveAndCloseChannelSocket(channel_name());
        }
#endif
        g_plugin_channels_.erase(iter);
        return;
      }
    }

    NOTREACHED();
  }
}

void PluginChannelBase::OnControlMessageReceived(const IPC::Message& msg) {
  NOTREACHED() <<
      "should override in subclass if you care about control messages";
}

void PluginChannelBase::OnChannelError() {
#if defined(OS_POSIX)
  if (channel_valid()) {
    IPC::RemoveAndCloseChannelSocket(channel_name());
  }
#endif
  channel_valid_ = false;
}

void PluginChannelBase::SendUnblockingOnlyDuringSyncDispatch() {
  send_unblocking_only_during_sync_dispatch_ = true;
}
