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 <set> 7 #include <vector> 8 9 #include "base/atomic_sequence_num.h" 10 #include "base/basictypes.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_vector.h" 13 #include "base/strings/string16.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/synchronization/lock.h" 16 #include "content/browser/message_port_message_filter.h" 17 #include "content/browser/shared_worker/shared_worker_message_filter.h" 18 #include "content/browser/shared_worker/shared_worker_service_impl.h" 19 #include "content/browser/worker_host/worker_storage_partition.h" 20 #include "content/common/message_port_messages.h" 21 #include "content/common/view_messages.h" 22 #include "content/common/worker_messages.h" 23 #include "content/public/test/test_browser_context.h" 24 #include "content/public/test/test_browser_thread_bundle.h" 25 #include "content/public/test/test_utils.h" 26 #include "ipc/ipc_sync_message.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 namespace content { 30 31 class SharedWorkerServiceImplTest : public testing::Test { 32 public: 33 static void RegisterRunningProcessID(int process_id) { 34 base::AutoLock lock(s_lock_); 35 s_running_process_id_set_.insert(process_id); 36 } 37 static void UnregisterRunningProcessID(int process_id) { 38 base::AutoLock lock(s_lock_); 39 s_running_process_id_set_.erase(process_id); 40 } 41 42 protected: 43 SharedWorkerServiceImplTest() 44 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), 45 browser_context_(new TestBrowserContext()), 46 partition_( 47 new WorkerStoragePartition(browser_context_->GetRequestContext(), 48 NULL, 49 NULL, 50 NULL, 51 NULL, 52 NULL, 53 NULL, 54 NULL)) { 55 SharedWorkerServiceImpl::GetInstance() 56 ->ChangeUpdateWorkerDependencyFuncForTesting( 57 &SharedWorkerServiceImplTest::MockUpdateWorkerDependency); 58 SharedWorkerServiceImpl::GetInstance() 59 ->ChangeTryIncrementWorkerRefCountFuncForTesting( 60 &SharedWorkerServiceImplTest::MockTryIncrementWorkerRefCount); 61 } 62 63 virtual void SetUp() OVERRIDE {} 64 virtual void TearDown() OVERRIDE { 65 s_update_worker_dependency_call_count_ = 0; 66 s_worker_dependency_added_ids_.clear(); 67 s_worker_dependency_removed_ids_.clear(); 68 s_running_process_id_set_.clear(); 69 SharedWorkerServiceImpl::GetInstance()->ResetForTesting(); 70 } 71 static void MockUpdateWorkerDependency(const std::vector<int>& added_ids, 72 const std::vector<int>& removed_ids) { 73 ++s_update_worker_dependency_call_count_; 74 s_worker_dependency_added_ids_ = added_ids; 75 s_worker_dependency_removed_ids_ = removed_ids; 76 } 77 static bool MockTryIncrementWorkerRefCount(int worker_process_id) { 78 base::AutoLock lock(s_lock_); 79 return s_running_process_id_set_.find(worker_process_id) != 80 s_running_process_id_set_.end(); 81 } 82 83 TestBrowserThreadBundle browser_thread_bundle_; 84 scoped_ptr<TestBrowserContext> browser_context_; 85 scoped_ptr<WorkerStoragePartition> partition_; 86 static int s_update_worker_dependency_call_count_; 87 static std::vector<int> s_worker_dependency_added_ids_; 88 static std::vector<int> s_worker_dependency_removed_ids_; 89 static base::Lock s_lock_; 90 static std::set<int> s_running_process_id_set_; 91 DISALLOW_COPY_AND_ASSIGN(SharedWorkerServiceImplTest); 92 }; 93 94 // static 95 int SharedWorkerServiceImplTest::s_update_worker_dependency_call_count_; 96 std::vector<int> SharedWorkerServiceImplTest::s_worker_dependency_added_ids_; 97 std::vector<int> SharedWorkerServiceImplTest::s_worker_dependency_removed_ids_; 98 base::Lock SharedWorkerServiceImplTest::s_lock_; 99 std::set<int> SharedWorkerServiceImplTest::s_running_process_id_set_; 100 101 namespace { 102 103 static const int kProcessIDs[] = {100, 101, 102}; 104 static const unsigned long long kDocumentIDs[] = {200, 201, 202}; 105 static const int kRenderFrameRouteIDs[] = {300, 301, 302}; 106 107 class MockMessagePortMessageFilter : public MessagePortMessageFilter { 108 public: 109 MockMessagePortMessageFilter(const NextRoutingIDCallback& callback, 110 ScopedVector<IPC::Message>* message_queue) 111 : MessagePortMessageFilter(callback), message_queue_(message_queue) {} 112 113 virtual bool Send(IPC::Message* message) OVERRIDE { 114 if (!message_queue_) { 115 delete message; 116 return false; 117 } 118 message_queue_->push_back(message); 119 return true; 120 } 121 122 void Close() { 123 message_queue_ = NULL; 124 OnChannelClosing(); 125 } 126 127 private: 128 virtual ~MockMessagePortMessageFilter() {} 129 ScopedVector<IPC::Message>* message_queue_; 130 }; 131 132 class MockSharedWorkerMessageFilter : public SharedWorkerMessageFilter { 133 public: 134 MockSharedWorkerMessageFilter(int render_process_id, 135 ResourceContext* resource_context, 136 const WorkerStoragePartition& partition, 137 MessagePortMessageFilter* message_port_filter, 138 ScopedVector<IPC::Message>* message_queue) 139 : SharedWorkerMessageFilter(render_process_id, 140 resource_context, 141 partition, 142 message_port_filter), 143 message_queue_(message_queue) {} 144 145 virtual bool Send(IPC::Message* message) OVERRIDE { 146 if (!message_queue_) { 147 delete message; 148 return false; 149 } 150 message_queue_->push_back(message); 151 return true; 152 } 153 154 void Close() { 155 message_queue_ = NULL; 156 OnChannelClosing(); 157 } 158 159 private: 160 virtual ~MockSharedWorkerMessageFilter() {} 161 ScopedVector<IPC::Message>* message_queue_; 162 }; 163 164 class MockRendererProcessHost { 165 public: 166 MockRendererProcessHost(int process_id, 167 ResourceContext* resource_context, 168 const WorkerStoragePartition& partition) 169 : process_id_(process_id), 170 message_filter_(new MockMessagePortMessageFilter( 171 base::Bind(&base::AtomicSequenceNumber::GetNext, 172 base::Unretained(&next_routing_id_)), 173 &queued_messages_)), 174 worker_filter_(new MockSharedWorkerMessageFilter(process_id, 175 resource_context, 176 partition, 177 message_filter_.get(), 178 &queued_messages_)) { 179 SharedWorkerServiceImplTest::RegisterRunningProcessID(process_id); 180 } 181 182 ~MockRendererProcessHost() { 183 SharedWorkerServiceImplTest::UnregisterRunningProcessID(process_id_); 184 message_filter_->Close(); 185 worker_filter_->Close(); 186 } 187 188 bool OnMessageReceived(IPC::Message* message) { 189 scoped_ptr<IPC::Message> msg(message); 190 const bool ret = message_filter_->OnMessageReceived(*message) || 191 worker_filter_->OnMessageReceived(*message); 192 if (message->is_sync()) { 193 CHECK(!queued_messages_.empty()); 194 const IPC::Message* response_msg = queued_messages_.back(); 195 IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(message); 196 scoped_ptr<IPC::MessageReplyDeserializer> reply_serializer( 197 sync_msg->GetReplyDeserializer()); 198 bool result = reply_serializer->SerializeOutputParameters(*response_msg); 199 CHECK(result); 200 queued_messages_.pop_back(); 201 } 202 return ret; 203 } 204 205 size_t QueuedMessageCount() const { return queued_messages_.size(); } 206 207 scoped_ptr<IPC::Message> PopMessage() { 208 CHECK(queued_messages_.size()); 209 scoped_ptr<IPC::Message> msg(*queued_messages_.begin()); 210 queued_messages_.weak_erase(queued_messages_.begin()); 211 return msg.Pass(); 212 } 213 214 void FastShutdownIfPossible() { 215 SharedWorkerServiceImplTest::UnregisterRunningProcessID(process_id_); 216 } 217 218 private: 219 const int process_id_; 220 ScopedVector<IPC::Message> queued_messages_; 221 base::AtomicSequenceNumber next_routing_id_; 222 scoped_refptr<MockMessagePortMessageFilter> message_filter_; 223 scoped_refptr<MockSharedWorkerMessageFilter> worker_filter_; 224 }; 225 226 void CreateMessagePortPair(MockRendererProcessHost* renderer, 227 int* route_1, 228 int* port_1, 229 int* route_2, 230 int* port_2) { 231 EXPECT_TRUE(renderer->OnMessageReceived( 232 new MessagePortHostMsg_CreateMessagePort(route_1, port_1))); 233 EXPECT_TRUE(renderer->OnMessageReceived( 234 new MessagePortHostMsg_CreateMessagePort(route_2, port_2))); 235 EXPECT_TRUE(renderer->OnMessageReceived( 236 new MessagePortHostMsg_Entangle(*port_1, *port_2))); 237 EXPECT_TRUE(renderer->OnMessageReceived( 238 new MessagePortHostMsg_Entangle(*port_2, *port_1))); 239 } 240 241 void PostCreateWorker(MockRendererProcessHost* renderer, 242 const std::string& url, 243 const std::string& name, 244 unsigned long long document_id, 245 int render_frame_route_id, 246 int* connector_route_id) { 247 ViewHostMsg_CreateWorker_Params params; 248 params.url = GURL(url); 249 params.name = base::ASCIIToUTF16(name); 250 params.content_security_policy = base::string16(); 251 params.security_policy_type = blink::WebContentSecurityPolicyTypeReport; 252 params.document_id = document_id; 253 params.render_frame_route_id = render_frame_route_id; 254 EXPECT_TRUE(renderer->OnMessageReceived( 255 new ViewHostMsg_CreateWorker(params, connector_route_id))); 256 } 257 258 class MockSharedWorkerConnector { 259 public: 260 MockSharedWorkerConnector(MockRendererProcessHost* renderer_host) 261 : renderer_host_(renderer_host), 262 temporary_remote_port_route_id_(0), 263 remote_port_id_(0), 264 local_port_route_id_(0), 265 local_port_id_(0), 266 route_id_(0) {} 267 void Create(const std::string& url, 268 const std::string& name, 269 unsigned long long document_id, 270 int render_frame_route_id) { 271 CreateMessagePortPair(renderer_host_, 272 &temporary_remote_port_route_id_, 273 &remote_port_id_, 274 &local_port_route_id_, 275 &local_port_id_); 276 PostCreateWorker(renderer_host_, 277 url, 278 name, 279 document_id, 280 render_frame_route_id, 281 &route_id_); 282 } 283 void SendQueueMessages() { 284 EXPECT_TRUE(renderer_host_->OnMessageReceived( 285 new MessagePortHostMsg_QueueMessages(remote_port_id_))); 286 } 287 void SendPostMessage(std::string data) { 288 const std::vector<int> empty_ids; 289 EXPECT_TRUE( 290 renderer_host_->OnMessageReceived(new MessagePortHostMsg_PostMessage( 291 local_port_id_, base::ASCIIToUTF16(data), empty_ids))); 292 } 293 void SendConnect() { 294 EXPECT_TRUE( 295 renderer_host_->OnMessageReceived(new ViewHostMsg_ForwardToWorker( 296 WorkerMsg_Connect(route_id_, remote_port_id_, MSG_ROUTING_NONE)))); 297 } 298 void SendSendQueuedMessages( 299 const std::vector<QueuedMessage>& queued_messages) { 300 EXPECT_TRUE(renderer_host_->OnMessageReceived( 301 new MessagePortHostMsg_SendQueuedMessages(remote_port_id_, 302 queued_messages))); 303 } 304 int temporary_remote_port_route_id() { 305 return temporary_remote_port_route_id_; 306 } 307 int remote_port_id() { return remote_port_id_; } 308 int local_port_route_id() { return local_port_route_id_; } 309 int local_port_id() { return local_port_id_; } 310 int route_id() { return route_id_; } 311 312 private: 313 MockRendererProcessHost* renderer_host_; 314 int temporary_remote_port_route_id_; 315 int remote_port_id_; 316 int local_port_route_id_; 317 int local_port_id_; 318 int route_id_; 319 }; 320 321 void CheckWorkerProcessMsgCreateWorker( 322 MockRendererProcessHost* renderer_host, 323 const std::string& expected_url, 324 const std::string& expected_name, 325 blink::WebContentSecurityPolicyType expected_security_policy_type, 326 int* route_id) { 327 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 328 EXPECT_EQ(WorkerProcessMsg_CreateWorker::ID, msg->type()); 329 Tuple1<WorkerProcessMsg_CreateWorker_Params> param; 330 EXPECT_TRUE(WorkerProcessMsg_CreateWorker::Read(msg.get(), ¶m)); 331 EXPECT_EQ(GURL(expected_url), param.a.url); 332 EXPECT_EQ(base::ASCIIToUTF16(expected_name), param.a.name); 333 EXPECT_EQ(expected_security_policy_type, param.a.security_policy_type); 334 *route_id = param.a.route_id; 335 } 336 337 void CheckViewMsgWorkerCreated(MockRendererProcessHost* renderer_host, 338 MockSharedWorkerConnector* connector) { 339 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 340 EXPECT_EQ(ViewMsg_WorkerCreated::ID, msg->type()); 341 EXPECT_EQ(connector->route_id(), msg->routing_id()); 342 } 343 344 void CheckMessagePortMsgMessagesQueued(MockRendererProcessHost* renderer_host, 345 MockSharedWorkerConnector* connector) { 346 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 347 EXPECT_EQ(MessagePortMsg_MessagesQueued::ID, msg->type()); 348 EXPECT_EQ(connector->temporary_remote_port_route_id(), msg->routing_id()); 349 } 350 351 void CheckWorkerMsgConnect(MockRendererProcessHost* renderer_host, 352 int expected_msg_route_id, 353 int expected_sent_message_port_id, 354 int* routing_id) { 355 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 356 EXPECT_EQ(WorkerMsg_Connect::ID, msg->type()); 357 EXPECT_EQ(expected_msg_route_id, msg->routing_id()); 358 WorkerMsg_Connect::Param params; 359 EXPECT_TRUE(WorkerMsg_Connect::Read(msg.get(), ¶ms)); 360 int port_id = params.a; 361 *routing_id = params.b; 362 EXPECT_EQ(expected_sent_message_port_id, port_id); 363 } 364 365 void CheckMessagePortMsgMessage(MockRendererProcessHost* renderer_host, 366 int expected_msg_route_id, 367 std::string expected_data) { 368 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 369 EXPECT_EQ(MessagePortMsg_Message::ID, msg->type()); 370 EXPECT_EQ(expected_msg_route_id, msg->routing_id()); 371 MessagePortMsg_Message::Param params; 372 EXPECT_TRUE(MessagePortMsg_Message::Read(msg.get(), ¶ms)); 373 base::string16 data = params.a; 374 EXPECT_EQ(base::ASCIIToUTF16(expected_data), data); 375 } 376 377 void CheckViewMsgWorkerConnected(MockRendererProcessHost* renderer_host, 378 MockSharedWorkerConnector* connector) { 379 scoped_ptr<IPC::Message> msg(renderer_host->PopMessage()); 380 EXPECT_EQ(ViewMsg_WorkerConnected::ID, msg->type()); 381 EXPECT_EQ(connector->route_id(), msg->routing_id()); 382 } 383 384 } // namespace 385 386 TEST_F(SharedWorkerServiceImplTest, BasicTest) { 387 scoped_ptr<MockRendererProcessHost> renderer_host( 388 new MockRendererProcessHost(kProcessIDs[0], 389 browser_context_->GetResourceContext(), 390 *partition_.get())); 391 scoped_ptr<MockSharedWorkerConnector> connector( 392 new MockSharedWorkerConnector(renderer_host.get())); 393 int worker_route_id; 394 int worker_msg_port_route_id; 395 396 // SharedWorkerConnector creates two message ports and sends 397 // ViewHostMsg_CreateWorker. 398 connector->Create("http://example.com/w.js", 399 "name", 400 kDocumentIDs[0], 401 kRenderFrameRouteIDs[0]); 402 // We need to go to UI thread to call ReserveRenderProcessOnUI(). 403 RunAllPendingInMessageLoop(); 404 EXPECT_EQ(2U, renderer_host->QueuedMessageCount()); 405 // WorkerProcessMsg_CreateWorker should be sent to the renderer in which 406 // SharedWorker will be created. 407 CheckWorkerProcessMsgCreateWorker(renderer_host.get(), 408 "http://example.com/w.js", 409 "name", 410 blink::WebContentSecurityPolicyTypeReport, 411 &worker_route_id); 412 // ViewMsg_WorkerCreated(1) should be sent back to SharedWorkerConnector side. 413 CheckViewMsgWorkerCreated(renderer_host.get(), connector.get()); 414 415 // SharedWorkerConnector side sends MessagePortHostMsg_QueueMessages in 416 // WebSharedWorkerProxy::connect. 417 connector->SendQueueMessages(); 418 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 419 // MessagePortMsg_MessagesQueued(2) should be sent back to 420 // SharedWorkerConnector side. 421 CheckMessagePortMsgMessagesQueued(renderer_host.get(), connector.get()); 422 423 // When SharedWorkerConnector receives ViewMsg_WorkerCreated(1), it sends 424 // WorkerMsg_Connect wrapped in ViewHostMsg_ForwardToWorker. 425 connector->SendConnect(); 426 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 427 // WorkerMsg_Connect should be sent to SharedWorker side. 428 CheckWorkerMsgConnect(renderer_host.get(), 429 worker_route_id, 430 connector->remote_port_id(), 431 &worker_msg_port_route_id); 432 433 // When SharedWorkerConnector receives MessagePortMsg_MessagesQueued(2), it 434 // sends MessagePortHostMsg_SendQueuedMessages. 435 std::vector<QueuedMessage> empty_messages; 436 connector->SendSendQueuedMessages(empty_messages); 437 EXPECT_EQ(0U, renderer_host->QueuedMessageCount()); 438 439 // SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in 440 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 441 EXPECT_TRUE(renderer_host->OnMessageReceived( 442 new WorkerHostMsg_WorkerScriptLoaded(worker_route_id))); 443 EXPECT_EQ(0U, renderer_host->QueuedMessageCount()); 444 445 // SharedWorker sends WorkerHostMsg_WorkerConnected in 446 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 447 EXPECT_TRUE( 448 renderer_host->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 449 connector->remote_port_id(), worker_route_id))); 450 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 451 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 452 CheckViewMsgWorkerConnected(renderer_host.get(), connector.get()); 453 454 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 455 // SharedWorker side shuold receive MessagePortMsg_Message. 456 connector->SendPostMessage("test1"); 457 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 458 CheckMessagePortMsgMessage( 459 renderer_host.get(), worker_msg_port_route_id, "test1"); 460 461 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 462 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 463 const std::vector<int> empty_ids; 464 EXPECT_TRUE(renderer_host->OnMessageReceived( 465 new MessagePortHostMsg_PostMessage(connector->remote_port_id(), 466 base::ASCIIToUTF16("test2"), 467 empty_ids))); 468 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 469 CheckMessagePortMsgMessage( 470 renderer_host.get(), connector->local_port_route_id(), "test2"); 471 472 // UpdateWorkerDependency should not be called. 473 EXPECT_EQ(0, s_update_worker_dependency_call_count_); 474 } 475 476 TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) { 477 // The first renderer host. 478 scoped_ptr<MockRendererProcessHost> renderer_host0( 479 new MockRendererProcessHost(kProcessIDs[0], 480 browser_context_->GetResourceContext(), 481 *partition_.get())); 482 scoped_ptr<MockSharedWorkerConnector> connector0( 483 new MockSharedWorkerConnector(renderer_host0.get())); 484 int worker_route_id; 485 int worker_msg_port_route_id1; 486 487 // SharedWorkerConnector creates two message ports and sends 488 // ViewHostMsg_CreateWorker. 489 connector0->Create("http://example.com/w.js", 490 "name", 491 kDocumentIDs[0], 492 kRenderFrameRouteIDs[0]); 493 // We need to go to UI thread to call ReserveRenderProcessOnUI(). 494 RunAllPendingInMessageLoop(); 495 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 496 // WorkerProcessMsg_CreateWorker should be sent to the renderer in which 497 // SharedWorker will be created. 498 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 499 "http://example.com/w.js", 500 "name", 501 blink::WebContentSecurityPolicyTypeReport, 502 &worker_route_id); 503 // ViewMsg_WorkerCreated(1) should be sent back to SharedWorkerConnector side. 504 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 505 506 // SharedWorkerConnector side sends MessagePortHostMsg_QueueMessages in 507 // WebSharedWorkerProxy::connect. 508 connector0->SendQueueMessages(); 509 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 510 // MessagePortMsg_MessagesQueued(2) should be sent back to 511 // SharedWorkerConnector side. 512 CheckMessagePortMsgMessagesQueued(renderer_host0.get(), connector0.get()); 513 514 // When SharedWorkerConnector receives ViewMsg_WorkerCreated(1), it sends 515 // WorkerMsg_Connect wrapped in ViewHostMsg_ForwardToWorker. 516 connector0->SendConnect(); 517 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 518 // WorkerMsg_Connect should be sent to SharedWorker side. 519 CheckWorkerMsgConnect(renderer_host0.get(), 520 worker_route_id, 521 connector0->remote_port_id(), 522 &worker_msg_port_route_id1); 523 524 // When SharedWorkerConnector receives MessagePortMsg_MessagesQueued(2), it 525 // sends MessagePortHostMsg_SendQueuedMessages. 526 std::vector<QueuedMessage> empty_messages; 527 connector0->SendSendQueuedMessages(empty_messages); 528 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 529 530 // SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in 531 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 532 EXPECT_TRUE(renderer_host0->OnMessageReceived( 533 new WorkerHostMsg_WorkerScriptLoaded(worker_route_id))); 534 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 535 536 // SharedWorker sends WorkerHostMsg_WorkerConnected in 537 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 538 EXPECT_TRUE( 539 renderer_host0->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 540 connector0->remote_port_id(), worker_route_id))); 541 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 542 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 543 CheckViewMsgWorkerConnected(renderer_host0.get(), connector0.get()); 544 545 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 546 // SharedWorker side shuold receive MessagePortMsg_Message. 547 connector0->SendPostMessage("test1"); 548 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 549 CheckMessagePortMsgMessage( 550 renderer_host0.get(), worker_msg_port_route_id1, "test1"); 551 552 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 553 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 554 const std::vector<int> empty_ids; 555 EXPECT_TRUE(renderer_host0->OnMessageReceived( 556 new MessagePortHostMsg_PostMessage(connector0->remote_port_id(), 557 base::ASCIIToUTF16("test2"), 558 empty_ids))); 559 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 560 CheckMessagePortMsgMessage( 561 renderer_host0.get(), connector0->local_port_route_id(), "test2"); 562 563 // The second renderer host. 564 scoped_ptr<MockRendererProcessHost> renderer_host1( 565 new MockRendererProcessHost(kProcessIDs[1], 566 browser_context_->GetResourceContext(), 567 *partition_.get())); 568 scoped_ptr<MockSharedWorkerConnector> connector1( 569 new MockSharedWorkerConnector(renderer_host1.get())); 570 int worker_msg_port_route_id2; 571 572 // UpdateWorkerDependency should not be called yet. 573 EXPECT_EQ(0, s_update_worker_dependency_call_count_); 574 575 // SharedWorkerConnector creates two message ports and sends 576 // ViewHostMsg_CreateWorker. 577 connector1->Create("http://example.com/w.js", 578 "name", 579 kDocumentIDs[1], 580 kRenderFrameRouteIDs[1]); 581 // We need to go to UI thread to call ReserveRenderProcessOnUI(). 582 RunAllPendingInMessageLoop(); 583 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 584 // ViewMsg_WorkerCreated(3) should be sent back to SharedWorkerConnector side. 585 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 586 587 // UpdateWorkerDependency should be called. 588 EXPECT_EQ(1, s_update_worker_dependency_call_count_); 589 EXPECT_EQ(1U, s_worker_dependency_added_ids_.size()); 590 EXPECT_EQ(kProcessIDs[0], s_worker_dependency_added_ids_[0]); 591 EXPECT_EQ(0U, s_worker_dependency_removed_ids_.size()); 592 593 // SharedWorkerConnector side sends MessagePortHostMsg_QueueMessages in 594 // WebSharedWorkerProxy::connect. 595 connector1->SendQueueMessages(); 596 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 597 // MessagePortMsg_MessagesQueued(4) should be sent back to 598 // SharedWorkerConnector side. 599 CheckMessagePortMsgMessagesQueued(renderer_host1.get(), connector1.get()); 600 601 // When SharedWorkerConnector receives ViewMsg_WorkerCreated(3), it sends 602 // WorkerMsg_Connect wrapped in ViewHostMsg_ForwardToWorker. 603 connector1->SendConnect(); 604 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 605 // WorkerMsg_Connect should be sent to SharedWorker side. 606 CheckWorkerMsgConnect(renderer_host0.get(), 607 worker_route_id, 608 connector1->remote_port_id(), 609 &worker_msg_port_route_id2); 610 611 // When SharedWorkerConnector receives MessagePortMsg_MessagesQueued(4), it 612 // sends MessagePortHostMsg_SendQueuedMessages. 613 connector1->SendSendQueuedMessages(empty_messages); 614 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 615 616 // SharedWorker sends WorkerHostMsg_WorkerConnected in 617 // EmbeddedSharedWorkerStub::OnConnect(). 618 EXPECT_TRUE( 619 renderer_host0->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 620 connector1->remote_port_id(), worker_route_id))); 621 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 622 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 623 CheckViewMsgWorkerConnected(renderer_host1.get(), connector1.get()); 624 625 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 626 // SharedWorker side shuold receive MessagePortMsg_Message. 627 connector1->SendPostMessage("test3"); 628 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 629 CheckMessagePortMsgMessage( 630 renderer_host0.get(), worker_msg_port_route_id2, "test3"); 631 632 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 633 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 634 EXPECT_TRUE(renderer_host0->OnMessageReceived( 635 new MessagePortHostMsg_PostMessage(connector1->remote_port_id(), 636 base::ASCIIToUTF16("test4"), 637 empty_ids))); 638 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 639 CheckMessagePortMsgMessage( 640 renderer_host1.get(), connector1->local_port_route_id(), "test4"); 641 642 EXPECT_EQ(1, s_update_worker_dependency_call_count_); 643 renderer_host1.reset(); 644 // UpdateWorkerDependency should be called. 645 EXPECT_EQ(2, s_update_worker_dependency_call_count_); 646 EXPECT_EQ(0U, s_worker_dependency_added_ids_.size()); 647 EXPECT_EQ(1U, s_worker_dependency_removed_ids_.size()); 648 EXPECT_EQ(kProcessIDs[0], s_worker_dependency_removed_ids_[0]); 649 } 650 651 TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest) { 652 // The first renderer host. 653 scoped_ptr<MockRendererProcessHost> renderer_host0( 654 new MockRendererProcessHost(kProcessIDs[0], 655 browser_context_->GetResourceContext(), 656 *partition_.get())); 657 // The second renderer host. 658 scoped_ptr<MockRendererProcessHost> renderer_host1( 659 new MockRendererProcessHost(kProcessIDs[1], 660 browser_context_->GetResourceContext(), 661 *partition_.get())); 662 int worker_route_id; 663 664 // Normal case. 665 { 666 scoped_ptr<MockSharedWorkerConnector> connector0( 667 new MockSharedWorkerConnector(renderer_host0.get())); 668 scoped_ptr<MockSharedWorkerConnector> connector1( 669 new MockSharedWorkerConnector(renderer_host1.get())); 670 connector0->Create("http://example.com/w1.js", 671 "name1", 672 kDocumentIDs[0], 673 kRenderFrameRouteIDs[0]); 674 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 675 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 676 RunAllPendingInMessageLoop(); 677 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 678 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 679 "http://example.com/w1.js", 680 "name1", 681 blink::WebContentSecurityPolicyTypeReport, 682 &worker_route_id); 683 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 684 connector1->Create("http://example.com/w1.js", 685 "name1", 686 kDocumentIDs[1], 687 kRenderFrameRouteIDs[1]); 688 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 689 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 690 RunAllPendingInMessageLoop(); 691 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 692 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 693 } 694 695 // Normal case (URL mismatch). 696 { 697 scoped_ptr<MockSharedWorkerConnector> connector0( 698 new MockSharedWorkerConnector(renderer_host0.get())); 699 scoped_ptr<MockSharedWorkerConnector> connector1( 700 new MockSharedWorkerConnector(renderer_host1.get())); 701 connector0->Create("http://example.com/w2.js", 702 "name2", 703 kDocumentIDs[0], 704 kRenderFrameRouteIDs[0]); 705 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 706 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 707 RunAllPendingInMessageLoop(); 708 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 709 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 710 "http://example.com/w2.js", 711 "name2", 712 blink::WebContentSecurityPolicyTypeReport, 713 &worker_route_id); 714 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 715 connector1->Create("http://example.com/w2x.js", 716 "name2", 717 kDocumentIDs[1], 718 kRenderFrameRouteIDs[1]); 719 EXPECT_EQ(MSG_ROUTING_NONE, connector1->route_id()); 720 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 721 RunAllPendingInMessageLoop(); 722 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 723 } 724 725 // Pending case. 726 { 727 scoped_ptr<MockSharedWorkerConnector> connector0( 728 new MockSharedWorkerConnector(renderer_host0.get())); 729 scoped_ptr<MockSharedWorkerConnector> connector1( 730 new MockSharedWorkerConnector(renderer_host1.get())); 731 connector0->Create("http://example.com/w3.js", 732 "name3", 733 kDocumentIDs[0], 734 kRenderFrameRouteIDs[0]); 735 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 736 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 737 connector1->Create("http://example.com/w3.js", 738 "name3", 739 kDocumentIDs[1], 740 kRenderFrameRouteIDs[1]); 741 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 742 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 743 RunAllPendingInMessageLoop(); 744 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 745 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 746 "http://example.com/w3.js", 747 "name3", 748 blink::WebContentSecurityPolicyTypeReport, 749 &worker_route_id); 750 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 751 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 752 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 753 } 754 755 // Pending case (URL mismatch). 756 { 757 scoped_ptr<MockSharedWorkerConnector> connector0( 758 new MockSharedWorkerConnector(renderer_host0.get())); 759 scoped_ptr<MockSharedWorkerConnector> connector1( 760 new MockSharedWorkerConnector(renderer_host1.get())); 761 connector0->Create("http://example.com/w4.js", 762 "name4", 763 kDocumentIDs[0], 764 kRenderFrameRouteIDs[0]); 765 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 766 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 767 connector1->Create("http://example.com/w4x.js", 768 "name4", 769 kDocumentIDs[1], 770 kRenderFrameRouteIDs[1]); 771 EXPECT_EQ(MSG_ROUTING_NONE, connector1->route_id()); 772 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 773 RunAllPendingInMessageLoop(); 774 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 775 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 776 "http://example.com/w4.js", 777 "name4", 778 blink::WebContentSecurityPolicyTypeReport, 779 &worker_route_id); 780 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 781 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 782 } 783 } 784 785 TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) { 786 // Create three renderer hosts. 787 scoped_ptr<MockRendererProcessHost> renderer_host0( 788 new MockRendererProcessHost(kProcessIDs[0], 789 browser_context_->GetResourceContext(), 790 *partition_.get())); 791 scoped_ptr<MockRendererProcessHost> renderer_host1( 792 new MockRendererProcessHost(kProcessIDs[1], 793 browser_context_->GetResourceContext(), 794 *partition_.get())); 795 scoped_ptr<MockRendererProcessHost> renderer_host2( 796 new MockRendererProcessHost(kProcessIDs[2], 797 browser_context_->GetResourceContext(), 798 *partition_.get())); 799 int worker_route_id; 800 801 scoped_ptr<MockSharedWorkerConnector> connector0( 802 new MockSharedWorkerConnector(renderer_host0.get())); 803 scoped_ptr<MockSharedWorkerConnector> connector1( 804 new MockSharedWorkerConnector(renderer_host1.get())); 805 scoped_ptr<MockSharedWorkerConnector> connector2( 806 new MockSharedWorkerConnector(renderer_host2.get())); 807 connector0->Create("http://example.com/w1.js", 808 "name1", 809 kDocumentIDs[0], 810 kRenderFrameRouteIDs[0]); 811 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 812 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 813 RunAllPendingInMessageLoop(); 814 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 815 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 816 "http://example.com/w1.js", 817 "name1", 818 blink::WebContentSecurityPolicyTypeReport, 819 &worker_route_id); 820 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 821 renderer_host0->FastShutdownIfPossible(); 822 823 connector1->Create("http://example.com/w1.js", 824 "name1", 825 kDocumentIDs[1], 826 kRenderFrameRouteIDs[1]); 827 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 828 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 829 RunAllPendingInMessageLoop(); 830 EXPECT_EQ(2U, renderer_host1->QueuedMessageCount()); 831 CheckWorkerProcessMsgCreateWorker(renderer_host1.get(), 832 "http://example.com/w1.js", 833 "name1", 834 blink::WebContentSecurityPolicyTypeReport, 835 &worker_route_id); 836 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 837 838 connector2->Create("http://example.com/w1.js", 839 "name1", 840 kDocumentIDs[2], 841 kRenderFrameRouteIDs[2]); 842 EXPECT_NE(MSG_ROUTING_NONE, connector2->route_id()); 843 EXPECT_EQ(0U, renderer_host2->QueuedMessageCount()); 844 RunAllPendingInMessageLoop(); 845 EXPECT_EQ(1U, renderer_host2->QueuedMessageCount()); 846 CheckViewMsgWorkerCreated(renderer_host2.get(), connector2.get()); 847 } 848 849 TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) { 850 // Create three renderer hosts. 851 scoped_ptr<MockRendererProcessHost> renderer_host0( 852 new MockRendererProcessHost(kProcessIDs[0], 853 browser_context_->GetResourceContext(), 854 *partition_.get())); 855 scoped_ptr<MockRendererProcessHost> renderer_host1( 856 new MockRendererProcessHost(kProcessIDs[1], 857 browser_context_->GetResourceContext(), 858 *partition_.get())); 859 scoped_ptr<MockRendererProcessHost> renderer_host2( 860 new MockRendererProcessHost(kProcessIDs[2], 861 browser_context_->GetResourceContext(), 862 *partition_.get())); 863 int worker_route_id; 864 865 scoped_ptr<MockSharedWorkerConnector> connector0( 866 new MockSharedWorkerConnector(renderer_host0.get())); 867 scoped_ptr<MockSharedWorkerConnector> connector1( 868 new MockSharedWorkerConnector(renderer_host1.get())); 869 scoped_ptr<MockSharedWorkerConnector> connector2( 870 new MockSharedWorkerConnector(renderer_host2.get())); 871 connector0->Create("http://example.com/w1.js", 872 "name1", 873 kDocumentIDs[0], 874 kRenderFrameRouteIDs[0]); 875 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 876 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 877 renderer_host0->FastShutdownIfPossible(); 878 879 connector1->Create("http://example.com/w1.js", 880 "name1", 881 kDocumentIDs[1], 882 kRenderFrameRouteIDs[1]); 883 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 884 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 885 RunAllPendingInMessageLoop(); 886 EXPECT_EQ(2U, renderer_host1->QueuedMessageCount()); 887 CheckWorkerProcessMsgCreateWorker(renderer_host1.get(), 888 "http://example.com/w1.js", 889 "name1", 890 blink::WebContentSecurityPolicyTypeReport, 891 &worker_route_id); 892 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 893 894 connector2->Create("http://example.com/w1.js", 895 "name1", 896 kDocumentIDs[2], 897 kRenderFrameRouteIDs[2]); 898 EXPECT_NE(MSG_ROUTING_NONE, connector2->route_id()); 899 EXPECT_EQ(0U, renderer_host2->QueuedMessageCount()); 900 RunAllPendingInMessageLoop(); 901 EXPECT_EQ(1U, renderer_host2->QueuedMessageCount()); 902 CheckViewMsgWorkerCreated(renderer_host2.get(), connector2.get()); 903 } 904 905 } // namespace content 906