Home | History | Annotate | Download | only in ipc
      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 "build/build_config.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/pickle.h"
      9 #include "base/threading/thread.h"
     10 #include "ipc/ipc_message.h"
     11 #include "ipc/ipc_test_base.h"
     12 #include "ipc/message_filter.h"
     13 
     14 // Get basic type definitions.
     15 #define IPC_MESSAGE_IMPL
     16 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     17 
     18 // Generate constructors.
     19 #include "ipc/struct_constructor_macros.h"
     20 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     21 
     22 // Generate destructors.
     23 #include "ipc/struct_destructor_macros.h"
     24 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     25 
     26 // Generate param traits write methods.
     27 #include "ipc/param_traits_write_macros.h"
     28 namespace IPC {
     29 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     30 }  // namespace IPC
     31 
     32 // Generate param traits read methods.
     33 #include "ipc/param_traits_read_macros.h"
     34 namespace IPC {
     35 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     36 }  // namespace IPC
     37 
     38 // Generate param traits log methods.
     39 #include "ipc/param_traits_log_macros.h"
     40 namespace IPC {
     41 #include "ipc/ipc_channel_proxy_unittest_messages.h"
     42 }  // namespace IPC
     43 
     44 
     45 namespace {
     46 
     47 class QuitListener : public IPC::Listener {
     48  public:
     49   QuitListener() : bad_message_received_(false) {}
     50   virtual ~QuitListener() {}
     51 
     52   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     53     IPC_BEGIN_MESSAGE_MAP(QuitListener, message)
     54       IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
     55       IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
     56     IPC_END_MESSAGE_MAP()
     57     return true;
     58   }
     59 
     60   virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE {
     61     bad_message_received_ = true;
     62   }
     63 
     64   void OnQuit() {
     65     base::MessageLoop::current()->QuitWhenIdle();
     66   }
     67 
     68   void OnBadMessage(const BadType& bad_type) {
     69     // Should never be called since IPC wouldn't be deserialized correctly.
     70     CHECK(false);
     71   }
     72 
     73   bool bad_message_received_;
     74 };
     75 
     76 class ChannelReflectorListener : public IPC::Listener {
     77  public:
     78   ChannelReflectorListener() : channel_(NULL) {}
     79   virtual ~ChannelReflectorListener() {}
     80 
     81   void Init(IPC::Channel* channel) {
     82     DCHECK(!channel_);
     83     channel_ = channel;
     84   }
     85 
     86   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     87     IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
     88       IPC_MESSAGE_HANDLER(TestMsg_Bounce, OnTestBounce)
     89       IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage, OnSendBadMessage)
     90       IPC_MESSAGE_HANDLER(UtilityMsg_Bounce, OnUtilityBounce)
     91       IPC_MESSAGE_HANDLER(WorkerMsg_Bounce, OnBounce)
     92       IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
     93     IPC_END_MESSAGE_MAP()
     94     return true;
     95   }
     96 
     97   void OnTestBounce() {
     98     channel_->Send(new TestMsg_Bounce());
     99   }
    100 
    101   void OnSendBadMessage() {
    102     channel_->Send(new TestMsg_BadMessage(BadType()));
    103   }
    104 
    105   void OnUtilityBounce() {
    106     channel_->Send(new UtilityMsg_Bounce());
    107   }
    108 
    109   void OnBounce() {
    110     channel_->Send(new WorkerMsg_Bounce());
    111   }
    112 
    113   void OnQuit() {
    114     channel_->Send(new WorkerMsg_Quit());
    115     base::MessageLoop::current()->QuitWhenIdle();
    116   }
    117 
    118  private:
    119   IPC::Channel* channel_;
    120 };
    121 
    122 class MessageCountFilter : public IPC::MessageFilter {
    123  public:
    124   enum FilterEvent {
    125     NONE,
    126     FILTER_ADDED,
    127     CHANNEL_CONNECTED,
    128     CHANNEL_ERROR,
    129     CHANNEL_CLOSING,
    130     FILTER_REMOVED
    131   };
    132   MessageCountFilter()
    133       : messages_received_(0),
    134         supported_message_class_(0),
    135         is_global_filter_(true),
    136         last_filter_event_(NONE),
    137         message_filtering_enabled_(false) {}
    138 
    139   MessageCountFilter(uint32 supported_message_class)
    140       : messages_received_(0),
    141         supported_message_class_(supported_message_class),
    142         is_global_filter_(false),
    143         last_filter_event_(NONE),
    144         message_filtering_enabled_(false) {}
    145 
    146   virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
    147     EXPECT_TRUE(sender);
    148     EXPECT_EQ(NONE, last_filter_event_);
    149     last_filter_event_ = FILTER_ADDED;
    150   }
    151 
    152   virtual void OnChannelConnected(int32_t peer_pid) OVERRIDE {
    153     EXPECT_EQ(FILTER_ADDED, last_filter_event_);
    154     EXPECT_NE(static_cast<int32_t>(base::kNullProcessId), peer_pid);
    155     last_filter_event_ = CHANNEL_CONNECTED;
    156   }
    157 
    158   virtual void OnChannelError() OVERRIDE {
    159     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
    160     last_filter_event_ = CHANNEL_ERROR;
    161   }
    162 
    163   virtual void OnChannelClosing() OVERRIDE {
    164     // We may or may not have gotten OnChannelError; if not, the last event has
    165     // to be OnChannelConnected.
    166     if (last_filter_event_ != CHANNEL_ERROR)
    167       EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
    168     last_filter_event_ = CHANNEL_CLOSING;
    169   }
    170 
    171   virtual void OnFilterRemoved() OVERRIDE {
    172     // If the channel didn't get a chance to connect, we might see the
    173     // OnFilterRemoved event with no other events preceding it. We still want
    174     // OnFilterRemoved to be called to allow for deleting the Filter.
    175     if (last_filter_event_ != NONE)
    176       EXPECT_EQ(CHANNEL_CLOSING, last_filter_event_);
    177     last_filter_event_ = FILTER_REMOVED;
    178   }
    179 
    180   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    181     // We should always get the OnFilterAdded and OnChannelConnected events
    182     // prior to any messages.
    183     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
    184 
    185     if (!is_global_filter_) {
    186       EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
    187     }
    188     ++messages_received_;
    189 
    190     if (!message_filtering_enabled_)
    191       return false;
    192 
    193     bool handled = true;
    194     IPC_BEGIN_MESSAGE_MAP(MessageCountFilter, message)
    195       IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
    196       IPC_MESSAGE_UNHANDLED(handled = false)
    197     IPC_END_MESSAGE_MAP()
    198     return handled;
    199   }
    200 
    201   void OnBadMessage(const BadType& bad_type) {
    202     // Should never be called since IPC wouldn't be deserialized correctly.
    203     CHECK(false);
    204   }
    205 
    206   virtual bool GetSupportedMessageClasses(
    207       std::vector<uint32>* supported_message_classes) const OVERRIDE {
    208     if (is_global_filter_)
    209       return false;
    210     supported_message_classes->push_back(supported_message_class_);
    211     return true;
    212   }
    213 
    214   void set_message_filtering_enabled(bool enabled) {
    215     message_filtering_enabled_ = enabled;
    216   }
    217 
    218   size_t messages_received() const { return messages_received_; }
    219   FilterEvent last_filter_event() const { return last_filter_event_; }
    220 
    221  private:
    222   virtual ~MessageCountFilter() {}
    223 
    224   size_t messages_received_;
    225   uint32 supported_message_class_;
    226   bool is_global_filter_;
    227 
    228   FilterEvent last_filter_event_;
    229   bool message_filtering_enabled_;
    230 };
    231 
    232 class IPCChannelProxyTest : public IPCTestBase {
    233  public:
    234   IPCChannelProxyTest() {}
    235   virtual ~IPCChannelProxyTest() {}
    236 
    237   virtual void SetUp() OVERRIDE {
    238     IPCTestBase::SetUp();
    239 
    240     Init("ChannelProxyClient");
    241 
    242     thread_.reset(new base::Thread("ChannelProxyTestServerThread"));
    243     base::Thread::Options options;
    244     options.message_loop_type = base::MessageLoop::TYPE_IO;
    245     thread_->StartWithOptions(options);
    246 
    247     listener_.reset(new QuitListener());
    248     CreateChannelProxy(listener_.get(), thread_->message_loop_proxy().get());
    249 
    250     ASSERT_TRUE(StartClient());
    251   }
    252 
    253   virtual void TearDown() {
    254     DestroyChannelProxy();
    255     thread_.reset();
    256     listener_.reset();
    257     IPCTestBase::TearDown();
    258   }
    259 
    260   void SendQuitMessageAndWaitForIdle() {
    261     sender()->Send(new WorkerMsg_Quit);
    262     base::MessageLoop::current()->Run();
    263     EXPECT_TRUE(WaitForClientShutdown());
    264   }
    265 
    266   bool DidListenerGetBadMessage() {
    267     return listener_->bad_message_received_;
    268   }
    269 
    270  private:
    271   scoped_ptr<base::Thread> thread_;
    272   scoped_ptr<QuitListener> listener_;
    273 };
    274 
    275 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
    276   // Construct a filter per message class.
    277   std::vector<scoped_refptr<MessageCountFilter> > class_filters;
    278   class_filters.push_back(make_scoped_refptr(
    279       new MessageCountFilter(TestMsgStart)));
    280   class_filters.push_back(make_scoped_refptr(
    281       new MessageCountFilter(UtilityMsgStart)));
    282   for (size_t i = 0; i < class_filters.size(); ++i)
    283     channel_proxy()->AddFilter(class_filters[i].get());
    284 
    285   // Send a message for each class; each filter should receive just one message.
    286   sender()->Send(new TestMsg_Bounce());
    287   sender()->Send(new UtilityMsg_Bounce());
    288 
    289   // Send some messages not assigned to a specific or valid message class.
    290   sender()->Send(new WorkerMsg_Bounce);
    291 
    292   // Each filter should have received just the one sent message of the
    293   // corresponding class.
    294   SendQuitMessageAndWaitForIdle();
    295   for (size_t i = 0; i < class_filters.size(); ++i)
    296     EXPECT_EQ(1U, class_filters[i]->messages_received());
    297 }
    298 
    299 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
    300   // Add a class and global filter.
    301   scoped_refptr<MessageCountFilter> class_filter(
    302       new MessageCountFilter(TestMsgStart));
    303   class_filter->set_message_filtering_enabled(false);
    304   channel_proxy()->AddFilter(class_filter.get());
    305 
    306   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
    307   global_filter->set_message_filtering_enabled(false);
    308   channel_proxy()->AddFilter(global_filter.get());
    309 
    310   // A message  of class Test should be seen by both the global filter and
    311   // Test-specific filter.
    312   sender()->Send(new TestMsg_Bounce);
    313 
    314   // A message of a different class should be seen only by the global filter.
    315   sender()->Send(new UtilityMsg_Bounce);
    316 
    317   // Flush all messages.
    318   SendQuitMessageAndWaitForIdle();
    319 
    320   // The class filter should have received only the class-specific message.
    321   EXPECT_EQ(1U, class_filter->messages_received());
    322 
    323   // The global filter should have received both messages, as well as the final
    324   // QUIT message.
    325   EXPECT_EQ(3U, global_filter->messages_received());
    326 }
    327 
    328 TEST_F(IPCChannelProxyTest, FilterRemoval) {
    329   // Add a class and global filter.
    330   scoped_refptr<MessageCountFilter> class_filter(
    331       new MessageCountFilter(TestMsgStart));
    332   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
    333 
    334   // Add and remove both types of filters.
    335   channel_proxy()->AddFilter(class_filter.get());
    336   channel_proxy()->AddFilter(global_filter.get());
    337   channel_proxy()->RemoveFilter(global_filter.get());
    338   channel_proxy()->RemoveFilter(class_filter.get());
    339 
    340   // Send some messages; they should not be seen by either filter.
    341   sender()->Send(new TestMsg_Bounce);
    342   sender()->Send(new UtilityMsg_Bounce);
    343 
    344   // Ensure that the filters were removed and did not receive any messages.
    345   SendQuitMessageAndWaitForIdle();
    346   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
    347             global_filter->last_filter_event());
    348   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
    349             class_filter->last_filter_event());
    350   EXPECT_EQ(0U, class_filter->messages_received());
    351   EXPECT_EQ(0U, global_filter->messages_received());
    352 }
    353 
    354 // The test that follow trigger DCHECKS in debug build.
    355 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
    356 
    357 TEST_F(IPCChannelProxyTest, BadMessageOnListenerThread) {
    358   scoped_refptr<MessageCountFilter> class_filter(
    359       new MessageCountFilter(TestMsgStart));
    360   class_filter->set_message_filtering_enabled(false);
    361   channel_proxy()->AddFilter(class_filter.get());
    362 
    363   sender()->Send(new TestMsg_SendBadMessage());
    364 
    365   SendQuitMessageAndWaitForIdle();
    366   EXPECT_TRUE(DidListenerGetBadMessage());
    367 }
    368 
    369 TEST_F(IPCChannelProxyTest, BadMessageOnIPCThread) {
    370   scoped_refptr<MessageCountFilter> class_filter(
    371       new MessageCountFilter(TestMsgStart));
    372   class_filter->set_message_filtering_enabled(true);
    373   channel_proxy()->AddFilter(class_filter.get());
    374 
    375   sender()->Send(new TestMsg_SendBadMessage());
    376 
    377   SendQuitMessageAndWaitForIdle();
    378   EXPECT_TRUE(DidListenerGetBadMessage());
    379 }
    380 
    381 class IPCChannelBadMessageTest : public IPCTestBase {
    382  public:
    383   IPCChannelBadMessageTest() {}
    384   virtual ~IPCChannelBadMessageTest() {}
    385 
    386   virtual void SetUp() OVERRIDE {
    387     IPCTestBase::SetUp();
    388 
    389     Init("ChannelProxyClient");
    390 
    391     listener_.reset(new QuitListener());
    392     CreateChannel(listener_.get());
    393     ASSERT_TRUE(ConnectChannel());
    394 
    395     ASSERT_TRUE(StartClient());
    396   }
    397 
    398   virtual void TearDown() {
    399     listener_.reset();
    400     IPCTestBase::TearDown();
    401   }
    402 
    403   void SendQuitMessageAndWaitForIdle() {
    404     sender()->Send(new WorkerMsg_Quit);
    405     base::MessageLoop::current()->Run();
    406     EXPECT_TRUE(WaitForClientShutdown());
    407   }
    408 
    409   bool DidListenerGetBadMessage() {
    410     return listener_->bad_message_received_;
    411   }
    412 
    413  private:
    414   scoped_ptr<QuitListener> listener_;
    415 };
    416 
    417 #if !defined(OS_WIN)
    418   // TODO(jam): for some reason this is flaky on win buildbots.
    419 TEST_F(IPCChannelBadMessageTest, BadMessage) {
    420   sender()->Send(new TestMsg_SendBadMessage());
    421   SendQuitMessageAndWaitForIdle();
    422   EXPECT_TRUE(DidListenerGetBadMessage());
    423 }
    424 #endif
    425 
    426 #endif
    427 
    428 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
    429   base::MessageLoopForIO main_message_loop;
    430   ChannelReflectorListener listener;
    431   scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
    432       IPCTestBase::GetChannelName("ChannelProxyClient"),
    433       &listener));
    434   CHECK(channel->Connect());
    435   listener.Init(channel.get());
    436 
    437   base::MessageLoop::current()->Run();
    438   return 0;
    439 }
    440 
    441 }  // namespace
    442