OLD | NEW |
---|---|
(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 <map> | |
6 #include <vector> | |
7 | |
8 #include "base/basictypes.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/memory/scoped_vector.h" | |
11 #include "base/strings/string16.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "content/browser/message_port_message_filter.h" | |
14 #include "content/browser/shared_worker/shared_worker_message_filter.h" | |
15 #include "content/browser/shared_worker/shared_worker_service_impl.h" | |
16 #include "content/browser/worker_host/worker_storage_partition.h" | |
17 #include "content/common/message_port_messages.h" | |
18 #include "content/common/view_messages.h" | |
19 #include "content/common/worker_messages.h" | |
20 #include "content/public/test/test_browser_context.h" | |
21 #include "content/public/test/test_browser_thread_bundle.h" | |
22 #include "ipc/ipc_sync_message.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 namespace content { | |
26 namespace { | |
27 | |
28 class NumberGenerator : public base::RefCountedThreadSafe<NumberGenerator> { | |
kinuko
2014/03/10 04:25:43
You can probably use base::AtomicSequenceNumber in
horo
2014/03/10 11:48:31
Done.
| |
29 public: | |
30 explicit NumberGenerator(int initial_no) : no_(initial_no) {} | |
31 int Next() { return ++no_; } | |
32 | |
33 private: | |
34 friend class base::RefCountedThreadSafe<NumberGenerator>; | |
35 ~NumberGenerator() {} | |
36 int no_; | |
37 }; | |
38 | |
39 class MockMessagePortMessageFilter : public MessagePortMessageFilter { | |
40 public: | |
41 MockMessagePortMessageFilter(const NextRoutingIDCallback& callback, | |
42 ScopedVector<IPC::Message>* message_queue) | |
43 : MessagePortMessageFilter(callback), message_queue_(message_queue) {} | |
44 | |
45 virtual bool Send(IPC::Message* message) OVERRIDE { | |
46 if (message_queue_) | |
47 message_queue_->push_back(message); | |
48 return true; | |
49 } | |
50 | |
51 void Close() { | |
52 message_queue_ = NULL; | |
53 OnChannelClosing(); | |
54 } | |
55 | |
56 private: | |
57 virtual ~MockMessagePortMessageFilter() {} | |
58 ScopedVector<IPC::Message>* message_queue_; | |
59 }; | |
60 | |
61 class MockSharedWorkerMessageFilter : public SharedWorkerMessageFilter { | |
62 public: | |
63 MockSharedWorkerMessageFilter(int render_process_id, | |
64 ResourceContext* resource_context, | |
65 const WorkerStoragePartition& partition, | |
66 MessagePortMessageFilter* message_port_filter, | |
67 ScopedVector<IPC::Message>* message_queue) | |
68 : SharedWorkerMessageFilter(render_process_id, | |
69 resource_context, | |
70 partition, | |
71 message_port_filter), | |
72 message_queue_(message_queue) {} | |
73 | |
74 virtual bool Send(IPC::Message* message) OVERRIDE { | |
75 if (message_queue_) | |
76 message_queue_->push_back(message); | |
77 return true; | |
78 } | |
79 | |
80 void Close() { | |
81 message_queue_ = NULL; | |
82 OnChannelClosing(); | |
83 } | |
84 | |
85 private: | |
86 virtual ~MockSharedWorkerMessageFilter() {} | |
87 ScopedVector<IPC::Message>* message_queue_; | |
88 }; | |
89 | |
90 class MockRenderer { | |
91 public: | |
92 MockRenderer(int initial_no, | |
93 int process_no, | |
94 ResourceContext* resource_context, | |
95 const WorkerStoragePartition& partition) | |
96 : num_generator_(new NumberGenerator(initial_no)), | |
97 message_filter_(new MockMessagePortMessageFilter( | |
98 base::Bind(&NumberGenerator::Next, num_generator_), | |
99 &queued_messages_)), | |
100 worker_filter_(new MockSharedWorkerMessageFilter(process_no, | |
101 resource_context, | |
102 partition, | |
103 message_filter_.get(), | |
104 &queued_messages_)) {} | |
105 | |
106 ~MockRenderer() { | |
107 message_filter_->Close(); | |
108 worker_filter_->Close(); | |
109 } | |
110 | |
111 bool Post(IPC::Message* message) { | |
kinuko
2014/03/10 04:25:43
MockRenderer -> MockRendererProcessHost
Post -> On
horo
2014/03/10 11:48:31
Done.
| |
112 scoped_ptr<IPC::Message> msg(message); | |
113 bool message_was_ok = false; | |
114 const bool ret = | |
115 message_filter_->OnMessageReceived(*message, &message_was_ok) || | |
116 worker_filter_->OnMessageReceived(*message, &message_was_ok); | |
117 if (message->is_sync()) { | |
118 CHECK(!queued_messages_.empty()); | |
119 const IPC::Message* responce_msg = queued_messages_.back(); | |
kinuko
2014/03/10 04:25:43
responce -> response
horo
2014/03/10 11:48:31
Done.
| |
120 IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(message); | |
121 scoped_ptr<IPC::MessageReplyDeserializer> reply_serializer( | |
122 sync_msg->GetReplyDeserializer()); | |
123 bool result = reply_serializer->SerializeOutputParameters(*responce_msg); | |
124 CHECK(result); | |
125 queued_messages_.pop_back(); | |
126 } | |
127 return ret; | |
128 } | |
129 | |
130 int QueuedMessageCount() { return queued_messages_.size(); } | |
kinuko
2014/03/10 04:25:43
nit: make it a const method
It'd be better to ret
horo
2014/03/10 11:48:31
Done.
| |
131 | |
132 IPC::Message* PopMessage() { | |
kinuko
2014/03/10 04:25:43
Can this return scoped_ptr<Message> (and all Check
horo
2014/03/10 11:48:31
Done.
| |
133 CHECK(queued_messages_.size()); | |
134 IPC::Message* msg = *queued_messages_.begin(); | |
135 queued_messages_.weak_erase(queued_messages_.begin()); | |
136 return msg; | |
137 } | |
138 | |
139 private: | |
140 ScopedVector<IPC::Message> queued_messages_; | |
141 scoped_refptr<NumberGenerator> num_generator_; | |
142 scoped_refptr<MockMessagePortMessageFilter> message_filter_; | |
143 scoped_refptr<MockSharedWorkerMessageFilter> worker_filter_; | |
144 }; | |
145 | |
146 void CreateMessagePortPair(MockRenderer* renderer, | |
147 int* route_1, | |
148 int* port_1, | |
149 int* route_2, | |
150 int* port_2) { | |
151 EXPECT_TRUE(renderer->Post( | |
152 new MessagePortHostMsg_CreateMessagePort(route_1, port_1))); | |
153 EXPECT_TRUE(renderer->Post( | |
154 new MessagePortHostMsg_CreateMessagePort(route_2, port_2))); | |
155 EXPECT_TRUE( | |
156 renderer->Post(new MessagePortHostMsg_Entangle(*port_1, *port_2))); | |
157 EXPECT_TRUE( | |
158 renderer->Post(new MessagePortHostMsg_Entangle(*port_2, *port_1))); | |
159 } | |
160 | |
161 void PostCreateWorker(MockRenderer* renderer, | |
162 const std::string& url, | |
163 const std::string& name, | |
164 unsigned long long document_id, | |
165 int render_frame_route_id, | |
166 int* connector_route_id) { | |
167 ViewHostMsg_CreateWorker_Params params; | |
168 params.url = GURL(url); | |
169 params.name = base::ASCIIToUTF16(name); | |
170 params.content_security_policy = base::string16(); | |
171 params.security_policy_type = blink::WebContentSecurityPolicyTypeReport; | |
172 params.document_id = document_id; | |
173 params.render_frame_route_id = render_frame_route_id; | |
174 EXPECT_TRUE( | |
175 renderer->Post(new ViewHostMsg_CreateWorker(params, connector_route_id))); | |
176 } | |
177 | |
178 void CheckWorkerProcessMsgCreateWorker( | |
179 IPC::Message* msg, | |
180 const std::string& url, | |
181 const std::string& name, | |
182 blink::WebContentSecurityPolicyType security_policy_type, | |
183 int route_id) { | |
kinuko
2014/03/10 04:25:43
nit: it'd read better if these params are prefixed
horo
2014/03/10 11:48:31
Done.
| |
184 scoped_ptr<IPC::Message> message(msg); | |
185 EXPECT_EQ(WorkerProcessMsg_CreateWorker::ID, msg->type()); | |
186 Tuple1<WorkerProcessMsg_CreateWorker_Params> param; | |
187 EXPECT_TRUE(WorkerProcessMsg_CreateWorker::Read(msg, ¶m)); | |
188 EXPECT_EQ(GURL(url), param.a.url); | |
189 EXPECT_EQ(base::ASCIIToUTF16(name), param.a.name); | |
190 EXPECT_EQ(security_policy_type, param.a.security_policy_type); | |
191 EXPECT_EQ(route_id, param.a.route_id); | |
192 } | |
193 | |
194 void CheckViewMsgWorkerCreated(IPC::Message* msg, int msg_route_id) { | |
195 scoped_ptr<IPC::Message> message(msg); | |
196 EXPECT_EQ(ViewMsg_WorkerCreated::ID, msg->type()); | |
197 EXPECT_EQ(msg_route_id, msg->routing_id()); | |
198 } | |
199 | |
200 void CheckMessagePortMsgMessagesQueued(IPC::Message* msg, int msg_route_id) { | |
201 scoped_ptr<IPC::Message> message(msg); | |
202 EXPECT_EQ(MessagePortMsg_MessagesQueued::ID, msg->type()); | |
203 EXPECT_EQ(msg_route_id, msg->routing_id()); | |
204 } | |
205 | |
206 void CheckWorkerMsgConnect(IPC::Message* msg, | |
207 int msg_route_id, | |
208 int sent_message_port_id, | |
209 int routing_id) { | |
210 scoped_ptr<IPC::Message> message(msg); | |
211 EXPECT_EQ(WorkerMsg_Connect::ID, msg->type()); | |
212 EXPECT_EQ(msg_route_id, msg->routing_id()); | |
213 int port_id; | |
214 int port_route; | |
215 EXPECT_TRUE(WorkerMsg_Connect::Read(msg, &port_id, &port_route)); | |
216 EXPECT_EQ(sent_message_port_id, port_id); | |
217 EXPECT_EQ(routing_id, port_route); | |
218 } | |
219 | |
220 void CheckMessagePortMsgMessage(IPC::Message* msg, | |
221 int msg_route_id, | |
222 std::string expected_data) { | |
223 scoped_ptr<IPC::Message> message(msg); | |
224 EXPECT_EQ(MessagePortMsg_Message::ID, msg->type()); | |
225 EXPECT_EQ(msg_route_id, msg->routing_id()); | |
226 base::string16 data; | |
227 std::vector<int> sent_message_port_ids; | |
228 std::vector<int> new_routing_ids; | |
229 EXPECT_TRUE(MessagePortMsg_Message::Read( | |
230 msg, &data, &sent_message_port_ids, &new_routing_ids)); | |
231 EXPECT_EQ(base::ASCIIToUTF16(expected_data), data); | |
232 } | |
233 | |
234 void CheckViewMsgWorkerConnected(IPC::Message* msg, int msg_route_id) { | |
235 scoped_ptr<IPC::Message> message(msg); | |
236 EXPECT_EQ(ViewMsg_WorkerConnected::ID, msg->type()); | |
237 EXPECT_EQ(msg_route_id, msg->routing_id()); | |
238 } | |
239 | |
240 std::vector<std::pair<std::vector<int>, std::vector<int> > > | |
241 g_worker_dependency_updates; | |
kinuko
2014/03/10 04:25:43
nit: I think just having two std::vector<int> woul
horo
2014/03/10 11:48:31
Done.
| |
242 | |
243 void MockUpdateWorkerDependency(const std::vector<int> added_ids, | |
244 const std::vector<int> removed_ids) { | |
245 g_worker_dependency_updates.push_back(std::make_pair(added_ids, removed_ids)); | |
246 } | |
247 | |
248 } // namespace | |
249 | |
250 class SharedWorkerServiceImplTest : public testing::Test { | |
251 protected: | |
252 SharedWorkerServiceImplTest() | |
253 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), | |
254 browser_context_(new TestBrowserContext()), | |
255 partition_( | |
256 new WorkerStoragePartition(browser_context_->GetRequestContext(), | |
257 NULL, | |
258 NULL, | |
259 NULL, | |
260 NULL, | |
261 NULL, | |
262 NULL)) { | |
263 SharedWorkerServiceImpl::GetInstance() | |
264 ->ChangeUpdateWorkerDependencyFuncForTesting( | |
265 MockUpdateWorkerDependency); | |
266 } | |
267 | |
268 virtual void SetUp() {} | |
269 virtual void TearDown() { | |
kinuko
2014/03/10 04:25:43
OVERRIDE
horo
2014/03/10 11:48:31
Done.
| |
270 g_worker_dependency_updates.clear(); | |
271 SharedWorkerServiceImpl::GetInstance()->ResetForTesting(); | |
272 } | |
273 | |
274 TestBrowserThreadBundle browser_thread_bundle_; | |
275 scoped_ptr<TestBrowserContext> browser_context_; | |
276 scoped_ptr<WorkerStoragePartition> partition_; | |
277 DISALLOW_COPY_AND_ASSIGN(SharedWorkerServiceImplTest); | |
278 }; | |
279 | |
280 TEST_F(SharedWorkerServiceImplTest, SimpleTest) { | |
kinuko
2014/03/10 04:25:43
Can you add some more comments in the test code bo
horo
2014/03/10 11:48:31
Done.
| |
281 scoped_ptr<MockRenderer> renderer1(new MockRenderer( | |
282 100, 200, browser_context_->GetResourceContext(), *partition_.get())); | |
283 | |
284 int msg_port_route1_1, msg_port_id1_1; | |
285 int msg_port_route1_2, msg_port_id1_2; | |
286 CreateMessagePortPair(renderer1.get(), | |
287 &msg_port_route1_1, | |
288 &msg_port_id1_1, | |
289 &msg_port_route1_2, | |
290 &msg_port_id1_2); | |
291 EXPECT_EQ(101, msg_port_route1_1); | |
292 EXPECT_EQ(102, msg_port_route1_2); | |
293 | |
294 int connector_route_id1; | |
295 PostCreateWorker(renderer1.get(), | |
296 "http://example.com/w.js", | |
297 "name", | |
298 300, | |
299 400, | |
300 &connector_route_id1); | |
301 EXPECT_EQ(103, connector_route_id1); | |
302 EXPECT_EQ(2, renderer1->QueuedMessageCount()); | |
303 int worker_route_id = 104; | |
304 CheckWorkerProcessMsgCreateWorker(renderer1->PopMessage(), | |
305 "http://example.com/w.js", | |
306 "name", | |
307 blink::WebContentSecurityPolicyTypeReport, | |
308 worker_route_id); | |
309 CheckViewMsgWorkerCreated(renderer1->PopMessage(), connector_route_id1); | |
310 | |
311 EXPECT_TRUE( | |
312 renderer1->Post(new MessagePortHostMsg_QueueMessages(msg_port_id1_1))); | |
313 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
314 CheckMessagePortMsgMessagesQueued(renderer1->PopMessage(), msg_port_route1_1); | |
315 | |
316 const std::vector<int> empty_ids; | |
317 EXPECT_TRUE(renderer1->Post(new MessagePortHostMsg_PostMessage( | |
318 msg_port_id1_2, base::ASCIIToUTF16("test"), empty_ids))); | |
319 EXPECT_EQ(0, renderer1->QueuedMessageCount()); | |
320 | |
321 int new_msg_port_route1 = 105; | |
322 EXPECT_TRUE(renderer1->Post(new ViewHostMsg_ForwardToWorker(WorkerMsg_Connect( | |
323 connector_route_id1, msg_port_id1_1, MSG_ROUTING_NONE)))); | |
324 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
325 CheckWorkerMsgConnect(renderer1->PopMessage(), | |
326 worker_route_id, | |
327 msg_port_id1_1, | |
328 new_msg_port_route1); | |
329 | |
330 std::vector<QueuedMessage> queued_messages; | |
331 EXPECT_TRUE(renderer1->Post(new MessagePortHostMsg_SendQueuedMessages( | |
332 msg_port_id1_1, queued_messages))); | |
333 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
334 CheckMessagePortMsgMessage( | |
335 renderer1->PopMessage(), new_msg_port_route1, "test"); | |
336 | |
337 EXPECT_TRUE( | |
338 renderer1->Post(new WorkerHostMsg_WorkerScriptLoaded(worker_route_id))); | |
339 EXPECT_EQ(0, renderer1->QueuedMessageCount()); | |
340 | |
341 EXPECT_TRUE(renderer1->Post( | |
342 new WorkerHostMsg_WorkerConnected(msg_port_id1_1, worker_route_id))); | |
343 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
344 CheckViewMsgWorkerConnected(renderer1->PopMessage(), connector_route_id1); | |
345 | |
346 EXPECT_TRUE(renderer1->Post(new MessagePortHostMsg_PostMessage( | |
347 msg_port_id1_1, base::ASCIIToUTF16("test2"), empty_ids))); | |
348 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
349 CheckMessagePortMsgMessage( | |
350 renderer1->PopMessage(), msg_port_route1_2, "test2"); | |
351 | |
352 scoped_ptr<MockRenderer> renderer2(new MockRenderer( | |
353 500, 600, browser_context_->GetResourceContext(), *partition_.get())); | |
354 | |
355 int msg_port_route2_1, msg_port_id2_1; | |
356 int msg_port_route2_2, msg_port_id2_2; | |
357 CreateMessagePortPair(renderer2.get(), | |
358 &msg_port_route2_1, | |
359 &msg_port_id2_1, | |
360 &msg_port_route2_2, | |
361 &msg_port_id2_2); | |
362 EXPECT_EQ(501, msg_port_route2_1); | |
363 EXPECT_EQ(502, msg_port_route2_2); | |
364 | |
365 EXPECT_EQ(0U, g_worker_dependency_updates.size()); | |
366 | |
367 int connector_route_id2; | |
368 PostCreateWorker(renderer2.get(), | |
369 "http://example.com/w.js", | |
370 "name", | |
371 700, | |
372 800, | |
373 &connector_route_id2); | |
374 EXPECT_EQ(503, connector_route_id2); | |
375 EXPECT_EQ(1, renderer2->QueuedMessageCount()); | |
376 CheckViewMsgWorkerCreated(renderer2->PopMessage(), connector_route_id2); | |
377 | |
378 EXPECT_EQ(1U, g_worker_dependency_updates.size()); | |
379 EXPECT_EQ(1U, g_worker_dependency_updates[0].first.size()); | |
380 EXPECT_EQ(200, g_worker_dependency_updates[0].first[0]); | |
381 EXPECT_EQ(0U, g_worker_dependency_updates[0].second.size()); | |
382 | |
383 EXPECT_TRUE( | |
384 renderer2->Post(new MessagePortHostMsg_QueueMessages(msg_port_id2_1))); | |
385 EXPECT_EQ(1, renderer2->QueuedMessageCount()); | |
386 CheckMessagePortMsgMessagesQueued(renderer2->PopMessage(), msg_port_route2_1); | |
387 | |
388 int new_msg_port_route2 = 106; | |
389 EXPECT_TRUE(renderer2->Post(new ViewHostMsg_ForwardToWorker(WorkerMsg_Connect( | |
390 connector_route_id2, msg_port_id2_1, MSG_ROUTING_NONE)))); | |
391 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
392 CheckWorkerMsgConnect(renderer1->PopMessage(), | |
393 worker_route_id, | |
394 msg_port_id2_1, | |
395 new_msg_port_route2); | |
396 | |
397 EXPECT_TRUE(renderer2->Post(new MessagePortHostMsg_SendQueuedMessages( | |
398 msg_port_id2_1, queued_messages))); | |
399 EXPECT_EQ(0, renderer2->QueuedMessageCount()); | |
400 | |
401 EXPECT_TRUE(renderer1->Post( | |
402 new WorkerHostMsg_WorkerConnected(msg_port_id2_1, worker_route_id))); | |
403 EXPECT_EQ(1, renderer2->QueuedMessageCount()); | |
404 CheckViewMsgWorkerConnected(renderer2->PopMessage(), connector_route_id2); | |
405 | |
406 EXPECT_TRUE(renderer2->Post(new MessagePortHostMsg_PostMessage( | |
407 msg_port_id2_2, base::ASCIIToUTF16("test3"), empty_ids))); | |
408 EXPECT_EQ(1, renderer1->QueuedMessageCount()); | |
409 CheckMessagePortMsgMessage( | |
410 renderer1->PopMessage(), new_msg_port_route2, "test3"); | |
411 | |
412 EXPECT_TRUE(renderer1->Post(new MessagePortHostMsg_PostMessage( | |
413 msg_port_id2_1, base::ASCIIToUTF16("test4"), empty_ids))); | |
414 EXPECT_EQ(1, renderer2->QueuedMessageCount()); | |
415 CheckMessagePortMsgMessage( | |
416 renderer2->PopMessage(), msg_port_route2_2, "test4"); | |
417 | |
418 EXPECT_EQ(1U, g_worker_dependency_updates.size()); | |
419 renderer2.reset(); | |
420 EXPECT_EQ(2U, g_worker_dependency_updates.size()); | |
421 EXPECT_EQ(0U, g_worker_dependency_updates[1].first.size()); | |
422 EXPECT_EQ(1U, g_worker_dependency_updates[1].second.size()); | |
423 EXPECT_EQ(200, g_worker_dependency_updates[1].second[0]); | |
424 } | |
425 | |
426 } // namespace content | |
OLD | NEW |