Home | History | Annotate | Download | only in media
      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 "content/renderer/media/aec_dump_message_filter.h"
      6 
      7 #include "base/message_loop/message_loop_proxy.h"
      8 #include "content/common/media/aec_dump_messages.h"
      9 #include "content/renderer/media/webrtc_logging.h"
     10 #include "ipc/ipc_logging.h"
     11 #include "ipc/ipc_sender.h"
     12 
     13 namespace {
     14 const int kInvalidDelegateId = -1;
     15 }
     16 
     17 namespace content {
     18 
     19 AecDumpMessageFilter* AecDumpMessageFilter::g_filter = NULL;
     20 
     21 AecDumpMessageFilter::AecDumpMessageFilter(
     22     const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
     23     const scoped_refptr<base::MessageLoopProxy>& main_message_loop)
     24     : sender_(NULL),
     25       delegate_id_counter_(0),
     26       io_message_loop_(io_message_loop),
     27       main_message_loop_(main_message_loop) {
     28   DCHECK(!g_filter);
     29   g_filter = this;
     30 }
     31 
     32 AecDumpMessageFilter::~AecDumpMessageFilter() {
     33   DCHECK_EQ(g_filter, this);
     34   g_filter = NULL;
     35 }
     36 
     37 // static
     38 scoped_refptr<AecDumpMessageFilter> AecDumpMessageFilter::Get() {
     39   return g_filter;
     40 }
     41 
     42 void AecDumpMessageFilter::AddDelegate(
     43     AecDumpMessageFilter::AecDumpDelegate* delegate) {
     44   DCHECK(main_message_loop_->BelongsToCurrentThread());
     45   DCHECK(delegate);
     46   DCHECK_EQ(kInvalidDelegateId, GetIdForDelegate(delegate));
     47 
     48   int id = delegate_id_counter_++;
     49   delegates_[id] = delegate;
     50 
     51   io_message_loop_->PostTask(
     52       FROM_HERE,
     53       base::Bind(
     54           &AecDumpMessageFilter::RegisterAecDumpConsumer,
     55           this,
     56           id));
     57 }
     58 
     59 void AecDumpMessageFilter::RemoveDelegate(
     60     AecDumpMessageFilter::AecDumpDelegate* delegate) {
     61   DCHECK(main_message_loop_->BelongsToCurrentThread());
     62   DCHECK(delegate);
     63 
     64   int id = GetIdForDelegate(delegate);
     65   DCHECK_NE(kInvalidDelegateId, id);
     66   delegates_.erase(id);
     67 
     68   io_message_loop_->PostTask(
     69       FROM_HERE,
     70       base::Bind(
     71           &AecDumpMessageFilter::UnregisterAecDumpConsumer,
     72           this,
     73           id));
     74 }
     75 
     76 void AecDumpMessageFilter::Send(IPC::Message* message) {
     77   DCHECK(io_message_loop_->BelongsToCurrentThread());
     78   if (sender_)
     79     sender_->Send(message);
     80   else
     81     delete message;
     82 }
     83 
     84 void AecDumpMessageFilter::RegisterAecDumpConsumer(int id) {
     85   Send(new AecDumpMsg_RegisterAecDumpConsumer(id));
     86 }
     87 
     88 void AecDumpMessageFilter::UnregisterAecDumpConsumer(int id) {
     89   Send(new AecDumpMsg_UnregisterAecDumpConsumer(id));
     90 }
     91 
     92 bool AecDumpMessageFilter::OnMessageReceived(const IPC::Message& message) {
     93   DCHECK(io_message_loop_->BelongsToCurrentThread());
     94   bool handled = true;
     95   IPC_BEGIN_MESSAGE_MAP(AecDumpMessageFilter, message)
     96     IPC_MESSAGE_HANDLER(AecDumpMsg_EnableAecDump, OnEnableAecDump)
     97     IPC_MESSAGE_HANDLER(AecDumpMsg_DisableAecDump, OnDisableAecDump)
     98     IPC_MESSAGE_UNHANDLED(handled = false)
     99   IPC_END_MESSAGE_MAP()
    100   return handled;
    101 }
    102 
    103 void AecDumpMessageFilter::OnFilterAdded(IPC::Sender* sender) {
    104   DCHECK(io_message_loop_->BelongsToCurrentThread());
    105   sender_ = sender;
    106 }
    107 
    108 void AecDumpMessageFilter::OnFilterRemoved() {
    109   DCHECK(io_message_loop_->BelongsToCurrentThread());
    110 
    111   // Once removed, a filter will not be used again.  At this time the
    112   // observer must be notified so it releases its reference.
    113   OnChannelClosing();
    114 }
    115 
    116 void AecDumpMessageFilter::OnChannelClosing() {
    117   DCHECK(io_message_loop_->BelongsToCurrentThread());
    118   sender_ = NULL;
    119   main_message_loop_->PostTask(
    120       FROM_HERE,
    121       base::Bind(
    122           &AecDumpMessageFilter::DoChannelClosingOnDelegates,
    123           this));
    124 }
    125 
    126 void AecDumpMessageFilter::OnEnableAecDump(
    127     int id,
    128     IPC::PlatformFileForTransit file_handle) {
    129   DCHECK(io_message_loop_->BelongsToCurrentThread());
    130   main_message_loop_->PostTask(
    131       FROM_HERE,
    132       base::Bind(
    133           &AecDumpMessageFilter::DoEnableAecDump,
    134           this,
    135           id,
    136           file_handle));
    137 }
    138 
    139 void AecDumpMessageFilter::OnDisableAecDump() {
    140   DCHECK(io_message_loop_->BelongsToCurrentThread());
    141   main_message_loop_->PostTask(
    142       FROM_HERE,
    143       base::Bind(
    144           &AecDumpMessageFilter::DoDisableAecDump,
    145           this));
    146 }
    147 
    148 void AecDumpMessageFilter::DoEnableAecDump(
    149     int id,
    150     IPC::PlatformFileForTransit file_handle) {
    151   DCHECK(main_message_loop_->BelongsToCurrentThread());
    152   DelegateMap::iterator it = delegates_.find(id);
    153   if (it != delegates_.end()) {
    154     it->second->OnAecDumpFile(file_handle);
    155   } else {
    156     // Delegate has been removed, we must close the file.
    157     base::File file = IPC::PlatformFileForTransitToFile(file_handle);
    158     DCHECK(file.IsValid());
    159     file.Close();
    160   }
    161 }
    162 
    163 void AecDumpMessageFilter::DoDisableAecDump() {
    164   DCHECK(main_message_loop_->BelongsToCurrentThread());
    165   for (DelegateMap::iterator it = delegates_.begin();
    166        it != delegates_.end(); ++it) {
    167     it->second->OnDisableAecDump();
    168   }
    169 }
    170 
    171 void AecDumpMessageFilter::DoChannelClosingOnDelegates() {
    172   DCHECK(main_message_loop_->BelongsToCurrentThread());
    173   for (DelegateMap::iterator it = delegates_.begin();
    174        it != delegates_.end(); ++it) {
    175     it->second->OnIpcClosing();
    176   }
    177   delegates_.clear();
    178 }
    179 
    180 int AecDumpMessageFilter::GetIdForDelegate(
    181     AecDumpMessageFilter::AecDumpDelegate* delegate) {
    182   DCHECK(main_message_loop_->BelongsToCurrentThread());
    183   for (DelegateMap::iterator it = delegates_.begin();
    184        it != delegates_.end(); ++it) {
    185     if (it->second == delegate)
    186       return it->first;
    187   }
    188   return kInvalidDelegateId;
    189 }
    190 
    191 }  // namespace content
    192