// Copyright 2014 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/gpu//compositor_forwarding_message_filter.h"

#include "base/bind.h"
#include "base/location.h"
#include "content/common/view_messages.h"
#include "ipc/ipc_message.h"

namespace content {

CompositorForwardingMessageFilter::CompositorForwardingMessageFilter(
    base::TaskRunner* compositor_task_runner)
    : compositor_task_runner_(compositor_task_runner) {
  DCHECK(compositor_task_runner_.get());
  // This check will only be used by functions running on compositor thread.
  compositor_thread_checker_.DetachFromThread();
}

CompositorForwardingMessageFilter::~CompositorForwardingMessageFilter() {
}

void CompositorForwardingMessageFilter::AddHandlerOnCompositorThread(
    int routing_id,
    const Handler& handler) {
  DCHECK(compositor_thread_checker_.CalledOnValidThread());
  DCHECK(!handler.is_null());
  multi_handlers_.insert(std::make_pair(routing_id, handler));
}

void CompositorForwardingMessageFilter::RemoveHandlerOnCompositorThread(
    int routing_id,
    const Handler& handler) {
  DCHECK(compositor_thread_checker_.CalledOnValidThread());
  auto handlers = multi_handlers_.equal_range(routing_id);
  for (auto it = handlers.first; it != handlers.second; ++it) {
    if (it->second.Equals(handler)) {
      multi_handlers_.erase(it);
      return;
    }
  }
  NOTREACHED();
}

bool CompositorForwardingMessageFilter::OnMessageReceived(
    const IPC::Message& message) {
  switch(message.type()) {
    case ViewMsg_BeginFrame::ID:                 // Fall through.
    case ViewMsg_ReclaimCompositorResources::ID: // Fall through.
    case ViewMsg_SwapCompositorFrameAck::ID:     // Fall through.
    case ViewMsg_UpdateVSyncParameters::ID:
      break;
    default:
      return false;
  }

  compositor_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(
          &CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread,
          this,
          message));
  return true;
}

void CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread(
    const IPC::Message& message) {
  DCHECK(compositor_thread_checker_.CalledOnValidThread());
  auto handlers = multi_handlers_.equal_range(message.routing_id());
  if (handlers.first == handlers.second)
    return;

  for (auto it = handlers.first; it != handlers.second; ++it)
    it->second.Run(message);
}

}  // namespace content
