1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/renderer/media/cast_ipc_dispatcher.h"
6
7#include "chrome/common/cast_messages.h"
8#include "chrome/renderer/media/cast_transport_sender_ipc.h"
9#include "ipc/ipc_message_macros.h"
10
11CastIPCDispatcher* CastIPCDispatcher::global_instance_ = NULL;
12
13CastIPCDispatcher::CastIPCDispatcher(
14    const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
15    : sender_(NULL),
16      io_message_loop_(io_message_loop) {
17  DCHECK(io_message_loop_.get());
18  DCHECK(!global_instance_);
19}
20
21CastIPCDispatcher::~CastIPCDispatcher() {
22  DCHECK(io_message_loop_->BelongsToCurrentThread());
23  DCHECK(!global_instance_);
24}
25
26CastIPCDispatcher* CastIPCDispatcher::Get() {
27  return global_instance_;
28}
29
30void CastIPCDispatcher::Send(IPC::Message* message) {
31  DCHECK(io_message_loop_->BelongsToCurrentThread());
32  if (sender_) {
33    sender_->Send(message);
34  } else {
35    delete message;
36  }
37}
38
39int32 CastIPCDispatcher::AddSender(CastTransportSenderIPC* sender) {
40  return id_map_.Add(sender);
41}
42
43void CastIPCDispatcher::RemoveSender(int32 channel_id) {
44  return id_map_.Remove(channel_id);
45}
46
47bool CastIPCDispatcher::OnMessageReceived(const IPC::Message& message) {
48  DCHECK(io_message_loop_->BelongsToCurrentThread());
49  bool handled = true;
50  IPC_BEGIN_MESSAGE_MAP(CastIPCDispatcher, message)
51    IPC_MESSAGE_HANDLER(CastMsg_NotifyStatusChange, OnNotifyStatusChange)
52    IPC_MESSAGE_HANDLER(CastMsg_RawEvents, OnRawEvents)
53    IPC_MESSAGE_HANDLER(CastMsg_Rtt, OnRtt)
54    IPC_MESSAGE_HANDLER(CastMsg_RtcpCastMessage, OnRtcpCastMessage)
55    IPC_MESSAGE_UNHANDLED(handled = false);
56  IPC_END_MESSAGE_MAP();
57  return handled;
58}
59
60void CastIPCDispatcher::OnFilterAdded(IPC::Sender* sender) {
61  DCHECK(io_message_loop_->BelongsToCurrentThread());
62  DCHECK(!global_instance_);
63  global_instance_ = this;
64  sender_ = sender;
65}
66
67void CastIPCDispatcher::OnFilterRemoved() {
68  DCHECK(io_message_loop_->BelongsToCurrentThread());
69  DCHECK_EQ(this, global_instance_);
70  global_instance_ = NULL;
71  sender_ = NULL;
72}
73
74void CastIPCDispatcher::OnChannelClosing() {
75  DCHECK(io_message_loop_->BelongsToCurrentThread());
76  DCHECK_EQ(this, global_instance_);
77}
78
79void CastIPCDispatcher::OnNotifyStatusChange(
80    int32 channel_id,
81    media::cast::CastTransportStatus status) {
82  CastTransportSenderIPC* sender = id_map_.Lookup(channel_id);
83  if (sender) {
84    sender->OnNotifyStatusChange(status);
85  } else {
86    DVLOG(1)
87        << "CastIPCDispatcher::OnNotifystatusChange on non-existing channel.";
88  }
89}
90
91void CastIPCDispatcher::OnRawEvents(
92    int32 channel_id,
93    const std::vector<media::cast::PacketEvent>& packet_events,
94    const std::vector<media::cast::FrameEvent>& frame_events) {
95  CastTransportSenderIPC* sender = id_map_.Lookup(channel_id);
96  if (sender) {
97    sender->OnRawEvents(packet_events, frame_events);
98  } else {
99    DVLOG(1) << "CastIPCDispatcher::OnRawEvents on non-existing channel.";
100  }
101}
102
103void CastIPCDispatcher::OnRtt(int32 channel_id,
104                              uint32 ssrc,
105                              base::TimeDelta rtt) {
106  CastTransportSenderIPC* sender = id_map_.Lookup(channel_id);
107  if (sender) {
108    sender->OnRtt(ssrc, rtt);
109  } else {
110    DVLOG(1) << "CastIPCDispatcher::OnRtt on non-existing channel.";
111  }
112}
113
114void CastIPCDispatcher::OnRtcpCastMessage(
115    int32 channel_id,
116    uint32 ssrc,
117    const media::cast::RtcpCastMessage& cast_message) {
118  CastTransportSenderIPC* sender = id_map_.Lookup(channel_id);
119  if (sender) {
120    sender->OnRtcpCastMessage(ssrc, cast_message);
121  } else {
122    DVLOG(1) << "CastIPCDispatcher::OnRtt on non-existing channel.";
123  }
124}
125