Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(513)

Side by Side Diff: ipc/ipc_channel_proxy_unittest.cc

Issue 142923005: Allow MessageFilters to restrict listening to specific message classes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/ipc_channel_proxy.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_message_macros.h"
12 #include "ipc/ipc_test_base.h"
13
14 namespace {
15
16 #if defined(IPC_MESSAGE_START)
17 #undef IPC_MESSAGE_START
18 #endif
19
20 enum Command {
21 SEND,
22 QUIT
23 };
24
25 static void Send(IPC::Sender* sender,
26 int message_class,
27 Command command) {
28 const int IPC_MESSAGE_START = message_class;
29 IPC::Message* message = new IPC::Message(0,
30 IPC_MESSAGE_ID(),
31 IPC::Message::PRIORITY_NORMAL);
32 message->WriteInt(command);
33 sender->Send(message);
34 }
35
36 class QuitListener : public IPC::Listener {
37 public:
38 QuitListener() {}
39 virtual ~QuitListener() {}
40
41 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
42 PickleIterator iter(message);
43
44 int command = SEND;
45 EXPECT_TRUE(iter.ReadInt(&command));
46 if (command == QUIT)
47 base::MessageLoop::current()->QuitWhenIdle();
48
49 return true;
50 }
51 };
52
53 class ChannelReflectorListener : public IPC::Listener {
54 public:
55 ChannelReflectorListener() : channel_(NULL) {}
56 virtual ~ChannelReflectorListener() {}
57
58 void Init(IPC::Channel* channel) {
59 DCHECK(!channel_);
60 channel_ = channel;
61 }
62
63 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
64 CHECK(channel_);
65
66 PickleIterator iter(message);
67
68 int command = SEND;
69 EXPECT_TRUE(iter.ReadInt(&command));
70 if (command == QUIT) {
71 channel_->Send(new IPC::Message(message));
72 base::MessageLoop::current()->QuitWhenIdle();
73 return true;
74 }
75
76 channel_->Send(new IPC::Message(message));
77 return true;
78 }
79
80 private:
81 IPC::Channel* channel_;
82 };
83
84 class MessageCountFilter : public IPC::ChannelProxy::MessageFilter {
85 public:
86 MessageCountFilter()
87 : messages_received_(0),
88 supported_message_class_(0),
89 is_global_filter_(true),
90 filter_removed_(false),
91 message_filtering_enabled_(false) {}
92
93 MessageCountFilter(uint32 supported_message_class)
94 : messages_received_(0),
95 supported_message_class_(supported_message_class),
96 is_global_filter_(false),
97 filter_removed_(false),
98 message_filtering_enabled_(false) {}
99
100 virtual void OnFilterRemoved() OVERRIDE {
101 EXPECT_FALSE(filter_removed_);
102 filter_removed_ = true;
103 }
104
105 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
106 if (!is_global_filter_) {
107 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
108 }
109 ++messages_received_;
110 return message_filtering_enabled_;
111 }
112
113 virtual bool GetSupportedMessageClasses(
114 std::vector<uint32>* supported_message_classes) const OVERRIDE {
115 if (is_global_filter_)
116 return false;
117 supported_message_classes->push_back(supported_message_class_);
118 return true;
119 }
120
121 void set_message_filtering_enabled(bool enabled) {
122 message_filtering_enabled_ = enabled;
123 }
124
125 size_t messages_received() const { return messages_received_; }
126 bool filter_removed() const { return filter_removed_; }
127
128 private:
129 virtual ~MessageCountFilter() {}
130
131 size_t messages_received_;
132 uint32 supported_message_class_;
133 bool is_global_filter_;
134 bool filter_removed_;
135 bool message_filtering_enabled_;
136 };
137
138 class IPCChannelProxyTest : public IPCTestBase {
139 public:
140 IPCChannelProxyTest() {}
141 virtual ~IPCChannelProxyTest() {}
142
143 virtual void SetUp() OVERRIDE {
144 IPCTestBase::SetUp();
145
146 Init("ChannelProxyClient");
147
148 thread_.reset(new base::Thread("ChannelProxyTestServerThread"));
149 base::Thread::Options options;
150 options.message_loop_type = base::MessageLoop::TYPE_IO;
151 thread_->StartWithOptions(options);
152
153 listener_.reset(new QuitListener());
154 CreateChannelProxy(listener_.get(), thread_->message_loop_proxy().get());
155
156 ASSERT_TRUE(StartClient());
157 }
158
159 virtual void TearDown() {
160 DestroyChannelProxy();
161 thread_.reset();
162 listener_.reset();
163 IPCTestBase::TearDown();
164 }
165
166 void SendQuitMessageAndWaitForIdle() {
167 Send(sender(), -1, QUIT);
168 base::MessageLoop::current()->Run();
169 EXPECT_TRUE(WaitForClientShutdown());
170 }
171
172 private:
173 scoped_ptr<base::Thread> thread_;
174 scoped_ptr<QuitListener> listener_;
175 };
176
177 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
178 // Construct a filter per message class.
179 std::vector<scoped_refptr<MessageCountFilter> > class_filters;
180 for (uint32 i = 0; i < LastIPCMsgStart; ++i) {
181 class_filters.push_back(make_scoped_refptr(
182 new MessageCountFilter(i)));
183 channel_proxy()->AddFilter(class_filters.back().get());
184 }
185
186 // Send a message for each class; each filter should receive just one message.
187 for (uint32 i = 0; i < LastIPCMsgStart; ++i)
188 Send(sender(), i, SEND);
189
190 // Send some messages not assigned to a specific or valid message class.
191 Send(sender(), -1, SEND);
192 Send(sender(), LastIPCMsgStart, SEND);
193 Send(sender(), LastIPCMsgStart + 1, SEND);
194
195 // Each filter should have received just the one sent message of the
196 // corresponding class.
197 SendQuitMessageAndWaitForIdle();
198 for (size_t i = 0; i < class_filters.size(); ++i)
199 EXPECT_EQ(1U, class_filters[i]->messages_received());
200 }
201
202 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
203 // Add a class and global filter.
204 const int kMessageClass = 7;
205 scoped_refptr<MessageCountFilter> class_filter(
206 new MessageCountFilter(kMessageClass));
207 class_filter->set_message_filtering_enabled(false);
208 channel_proxy()->AddFilter(class_filter.get());
209
210 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
211 global_filter->set_message_filtering_enabled(false);
212 channel_proxy()->AddFilter(global_filter.get());
213
214 // A message of class |kMessageClass| should be seen by both the global
215 // filter and |kMessageClass|-specific filter.
216 Send(sender(), kMessageClass, SEND);
217
218 // A message of a different class should be seen only by the global filter.
219 Send(sender(), kMessageClass + 1, SEND);
220
221 // Flush all messages.
222 SendQuitMessageAndWaitForIdle();
223
224 // The class filter should have received only the class-specific message.
225 EXPECT_EQ(1U, class_filter->messages_received());
226
227 // The global filter should have received both SEND messages, as well as the
228 // final QUIT message.
229 EXPECT_EQ(3U, global_filter->messages_received());
230 }
231
232 TEST_F(IPCChannelProxyTest, FilterRemoval) {
233 // Add a class and global filter.
234 const int kMessageClass = 7;
235 scoped_refptr<MessageCountFilter> class_filter(
236 new MessageCountFilter(kMessageClass));
237 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
238
239 // Add and remove both types of filters.
240 channel_proxy()->AddFilter(class_filter.get());
241 channel_proxy()->AddFilter(global_filter.get());
242 channel_proxy()->RemoveFilter(global_filter.get());
243 channel_proxy()->RemoveFilter(class_filter.get());
244
245 // Send some messages; they should not be seen by either filter.
246 Send(sender(), 0, SEND);
247 Send(sender(), kMessageClass, SEND);
248
249 // Ensure that the filters were removed and did not receive any messages.
250 SendQuitMessageAndWaitForIdle();
251 EXPECT_TRUE(global_filter->filter_removed());
252 EXPECT_TRUE(class_filter->filter_removed());
253 EXPECT_EQ(0U, class_filter->messages_received());
254 EXPECT_EQ(0U, global_filter->messages_received());
255 }
256
257 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
258 base::MessageLoopForIO main_message_loop;
259 ChannelReflectorListener listener;
260 IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
261 IPC::Channel::MODE_CLIENT,
262 &listener);
263 CHECK(channel.Connect());
264 listener.Init(&channel);
265
266 base::MessageLoop::current()->Run();
267 return 0;
268 }
269
270 } // namespace
OLDNEW
« no previous file with comments | « ipc/ipc_channel_proxy.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698