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