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

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, 10 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 virtual void QuitAndWaitForIdle() {
167 Send(sender(), -1, QUIT);
168 base::MessageLoop::current()->Run();
169 thread_->message_loop()->RunUntilIdle();
piman 2014/02/14 22:05:05 I don't think this does what you want it to do. If
jdduke (slow) 2014/02/15 02:57:09 Done.
170 EXPECT_TRUE(WaitForClientShutdown());
171 }
172
173 private:
174 scoped_ptr<base::Thread> thread_;
175 scoped_ptr<QuitListener> listener_;
176 };
177
178 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
179 // Construct a filter per message class.
180 std::vector<scoped_refptr<MessageCountFilter> > class_filters;
181 for (size_t i = 0; i < LastIPCMsgStart; ++i) {
182 class_filters.push_back(make_scoped_refptr(
183 new MessageCountFilter(i)));
184 channel_proxy()->AddFilter(class_filters.back().get());
185 }
186
187 // Send a message for each class; each filter should receive just one message.
188 for (size_t i = 0; i < class_filters.size(); ++i)
189 Send(sender(), i, SEND);
190
191 // Send a message with an invalid class; this should not reach any filter.
192 Send(sender(), -1, SEND);
piman 2014/02/14 22:05:05 nit: -1 is special (for replies, etc.). You may wa
jdduke (slow) 2014/02/15 02:57:09 Done.
193
194 // All messages should have been received by their respective filter.
195 QuitAndWaitForIdle();
196 for (size_t i = 0; i < class_filters.size(); ++i)
197 EXPECT_EQ(1U, class_filters[i]->messages_received());
198 }
199
200 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
201 // Add a class and global filter.
202 const int kMessageClass = 7;
203 scoped_refptr<MessageCountFilter> class_filter(
204 new MessageCountFilter(kMessageClass));
205 class_filter->set_message_filtering_enabled(false);
206 channel_proxy()->AddFilter(class_filter.get());
207
208 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
209 global_filter->set_message_filtering_enabled(false);
210 channel_proxy()->AddFilter(global_filter.get());
211
212 // A message of class |kMessageClass| should be seen by both the global
213 // filter and |kMessageClass|-specific filter.
214 Send(sender(), kMessageClass, SEND);
215
216 // A message of a different class should be seen only by the global filter.
217 Send(sender(), kMessageClass + 1, SEND);
218
219 // Flush all messages.
220 QuitAndWaitForIdle();
221
222 // The class filter should have received only the class-specific message.
223 EXPECT_EQ(1U, class_filter->messages_received());
224
225 // The global filter should have received both SEND messages, as well as the
226 // final QUIT message.
227 EXPECT_EQ(3U, global_filter->messages_received());
228 }
229
230 TEST_F(IPCChannelProxyTest, FilterRemoval) {
231 // Add a class and global filter.
232 const int kMessageClass = 7;
233 scoped_refptr<MessageCountFilter> class_filter(
234 new MessageCountFilter(kMessageClass));
235 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
236
237 // Add and remove both types of filters.
238 channel_proxy()->AddFilter(class_filter.get());
239 channel_proxy()->AddFilter(global_filter.get());
240 channel_proxy()->RemoveFilter(global_filter.get());
241 channel_proxy()->RemoveFilter(class_filter.get());
242
243 // Send some messages; they should not be seen by either filter.
244 Send(sender(), kMessageClass, SEND);
245 Send(sender(), kMessageClass, SEND);
246
247 // Ensure that the filters were removed and did not receive any messages.
248 QuitAndWaitForIdle();
249 EXPECT_TRUE(global_filter->filter_removed());
250 EXPECT_TRUE(class_filter->filter_removed());
251 EXPECT_EQ(0U, class_filter->messages_received());
252 EXPECT_EQ(0U, global_filter->messages_received());
253 }
254
255 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
256 base::MessageLoopForIO main_message_loop;
257 ChannelReflectorListener listener;
258 IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
259 IPC::Channel::MODE_CLIENT,
260 &listener);
261 CHECK(channel.Connect());
262 listener.Init(&channel);
263
264 base::MessageLoop::current()->Run();
265 return 0;
266 }
267
268 } // namespace
OLDNEW
« content/browser/renderer_host/render_message_filter.cc ('K') | « ipc/ipc_channel_proxy.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698