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/shared_worker/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_WorkerReadyForInspection in 440 // EmbeddedSharedWorkerStub::WorkerReadyForInspection(). 441 EXPECT_TRUE(renderer_host->OnMessageReceived( 442 new WorkerHostMsg_WorkerReadyForInspection(worker_route_id))); 443 EXPECT_EQ(0U, renderer_host->QueuedMessageCount()); 444 445 // SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in 446 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 447 EXPECT_TRUE(renderer_host->OnMessageReceived( 448 new WorkerHostMsg_WorkerScriptLoaded(worker_route_id))); 449 EXPECT_EQ(0U, renderer_host->QueuedMessageCount()); 450 451 // SharedWorker sends WorkerHostMsg_WorkerConnected in 452 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 453 EXPECT_TRUE( 454 renderer_host->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 455 connector->remote_port_id(), worker_route_id))); 456 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 457 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 458 CheckViewMsgWorkerConnected(renderer_host.get(), connector.get()); 459 460 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 461 // SharedWorker side shuold receive MessagePortMsg_Message. 462 connector->SendPostMessage("test1"); 463 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 464 CheckMessagePortMsgMessage( 465 renderer_host.get(), worker_msg_port_route_id, "test1"); 466 467 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 468 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 469 const std::vector<int> empty_ids; 470 EXPECT_TRUE(renderer_host->OnMessageReceived( 471 new MessagePortHostMsg_PostMessage(connector->remote_port_id(), 472 base::ASCIIToUTF16("test2"), 473 empty_ids))); 474 EXPECT_EQ(1U, renderer_host->QueuedMessageCount()); 475 CheckMessagePortMsgMessage( 476 renderer_host.get(), connector->local_port_route_id(), "test2"); 477 478 // UpdateWorkerDependency should not be called. 479 EXPECT_EQ(0, s_update_worker_dependency_call_count_); 480 } 481 482 TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) { 483 // The first renderer host. 484 scoped_ptr<MockRendererProcessHost> renderer_host0( 485 new MockRendererProcessHost(kProcessIDs[0], 486 browser_context_->GetResourceContext(), 487 *partition_.get())); 488 scoped_ptr<MockSharedWorkerConnector> connector0( 489 new MockSharedWorkerConnector(renderer_host0.get())); 490 int worker_route_id; 491 int worker_msg_port_route_id1; 492 493 // SharedWorkerConnector creates two message ports and sends 494 // ViewHostMsg_CreateWorker. 495 connector0->Create("http://example.com/w.js", 496 "name", 497 kDocumentIDs[0], 498 kRenderFrameRouteIDs[0]); 499 // We need to go to UI thread to call ReserveRenderProcessOnUI(). 500 RunAllPendingInMessageLoop(); 501 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 502 // WorkerProcessMsg_CreateWorker should be sent to the renderer in which 503 // SharedWorker will be created. 504 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 505 "http://example.com/w.js", 506 "name", 507 blink::WebContentSecurityPolicyTypeReport, 508 &worker_route_id); 509 // ViewMsg_WorkerCreated(1) should be sent back to SharedWorkerConnector side. 510 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 511 512 // SharedWorkerConnector side sends MessagePortHostMsg_QueueMessages in 513 // WebSharedWorkerProxy::connect. 514 connector0->SendQueueMessages(); 515 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 516 // MessagePortMsg_MessagesQueued(2) should be sent back to 517 // SharedWorkerConnector side. 518 CheckMessagePortMsgMessagesQueued(renderer_host0.get(), connector0.get()); 519 520 // When SharedWorkerConnector receives ViewMsg_WorkerCreated(1), it sends 521 // WorkerMsg_Connect wrapped in ViewHostMsg_ForwardToWorker. 522 connector0->SendConnect(); 523 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 524 // WorkerMsg_Connect should be sent to SharedWorker side. 525 CheckWorkerMsgConnect(renderer_host0.get(), 526 worker_route_id, 527 connector0->remote_port_id(), 528 &worker_msg_port_route_id1); 529 530 // When SharedWorkerConnector receives MessagePortMsg_MessagesQueued(2), it 531 // sends MessagePortHostMsg_SendQueuedMessages. 532 std::vector<QueuedMessage> empty_messages; 533 connector0->SendSendQueuedMessages(empty_messages); 534 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 535 536 // SharedWorker sends WorkerHostMsg_WorkerReadyForInspection in 537 // EmbeddedSharedWorkerStub::WorkerReadyForInspection(). 538 EXPECT_TRUE(renderer_host0->OnMessageReceived( 539 new WorkerHostMsg_WorkerReadyForInspection(worker_route_id))); 540 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 541 542 // SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in 543 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 544 EXPECT_TRUE(renderer_host0->OnMessageReceived( 545 new WorkerHostMsg_WorkerScriptLoaded(worker_route_id))); 546 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 547 548 // SharedWorker sends WorkerHostMsg_WorkerConnected in 549 // EmbeddedSharedWorkerStub::workerScriptLoaded(). 550 EXPECT_TRUE( 551 renderer_host0->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 552 connector0->remote_port_id(), worker_route_id))); 553 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 554 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 555 CheckViewMsgWorkerConnected(renderer_host0.get(), connector0.get()); 556 557 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 558 // SharedWorker side shuold receive MessagePortMsg_Message. 559 connector0->SendPostMessage("test1"); 560 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 561 CheckMessagePortMsgMessage( 562 renderer_host0.get(), worker_msg_port_route_id1, "test1"); 563 564 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 565 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 566 const std::vector<int> empty_ids; 567 EXPECT_TRUE(renderer_host0->OnMessageReceived( 568 new MessagePortHostMsg_PostMessage(connector0->remote_port_id(), 569 base::ASCIIToUTF16("test2"), 570 empty_ids))); 571 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 572 CheckMessagePortMsgMessage( 573 renderer_host0.get(), connector0->local_port_route_id(), "test2"); 574 575 // The second renderer host. 576 scoped_ptr<MockRendererProcessHost> renderer_host1( 577 new MockRendererProcessHost(kProcessIDs[1], 578 browser_context_->GetResourceContext(), 579 *partition_.get())); 580 scoped_ptr<MockSharedWorkerConnector> connector1( 581 new MockSharedWorkerConnector(renderer_host1.get())); 582 int worker_msg_port_route_id2; 583 584 // UpdateWorkerDependency should not be called yet. 585 EXPECT_EQ(0, s_update_worker_dependency_call_count_); 586 587 // SharedWorkerConnector creates two message ports and sends 588 // ViewHostMsg_CreateWorker. 589 connector1->Create("http://example.com/w.js", 590 "name", 591 kDocumentIDs[1], 592 kRenderFrameRouteIDs[1]); 593 // We need to go to UI thread to call ReserveRenderProcessOnUI(). 594 RunAllPendingInMessageLoop(); 595 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 596 // ViewMsg_WorkerCreated(3) should be sent back to SharedWorkerConnector side. 597 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 598 599 // UpdateWorkerDependency should be called. 600 EXPECT_EQ(1, s_update_worker_dependency_call_count_); 601 EXPECT_EQ(1U, s_worker_dependency_added_ids_.size()); 602 EXPECT_EQ(kProcessIDs[0], s_worker_dependency_added_ids_[0]); 603 EXPECT_EQ(0U, s_worker_dependency_removed_ids_.size()); 604 605 // SharedWorkerConnector side sends MessagePortHostMsg_QueueMessages in 606 // WebSharedWorkerProxy::connect. 607 connector1->SendQueueMessages(); 608 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 609 // MessagePortMsg_MessagesQueued(4) should be sent back to 610 // SharedWorkerConnector side. 611 CheckMessagePortMsgMessagesQueued(renderer_host1.get(), connector1.get()); 612 613 // When SharedWorkerConnector receives ViewMsg_WorkerCreated(3), it sends 614 // WorkerMsg_Connect wrapped in ViewHostMsg_ForwardToWorker. 615 connector1->SendConnect(); 616 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 617 // WorkerMsg_Connect should be sent to SharedWorker side. 618 CheckWorkerMsgConnect(renderer_host0.get(), 619 worker_route_id, 620 connector1->remote_port_id(), 621 &worker_msg_port_route_id2); 622 623 // When SharedWorkerConnector receives MessagePortMsg_MessagesQueued(4), it 624 // sends MessagePortHostMsg_SendQueuedMessages. 625 connector1->SendSendQueuedMessages(empty_messages); 626 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 627 628 // SharedWorker sends WorkerHostMsg_WorkerConnected in 629 // EmbeddedSharedWorkerStub::OnConnect(). 630 EXPECT_TRUE( 631 renderer_host0->OnMessageReceived(new WorkerHostMsg_WorkerConnected( 632 connector1->remote_port_id(), worker_route_id))); 633 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 634 // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side. 635 CheckViewMsgWorkerConnected(renderer_host1.get(), connector1.get()); 636 637 // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage, 638 // SharedWorker side shuold receive MessagePortMsg_Message. 639 connector1->SendPostMessage("test3"); 640 EXPECT_EQ(1U, renderer_host0->QueuedMessageCount()); 641 CheckMessagePortMsgMessage( 642 renderer_host0.get(), worker_msg_port_route_id2, "test3"); 643 644 // When SharedWorker side sends MessagePortHostMsg_PostMessage, 645 // SharedWorkerConnector side shuold receive MessagePortMsg_Message. 646 EXPECT_TRUE(renderer_host0->OnMessageReceived( 647 new MessagePortHostMsg_PostMessage(connector1->remote_port_id(), 648 base::ASCIIToUTF16("test4"), 649 empty_ids))); 650 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 651 CheckMessagePortMsgMessage( 652 renderer_host1.get(), connector1->local_port_route_id(), "test4"); 653 654 EXPECT_EQ(1, s_update_worker_dependency_call_count_); 655 renderer_host1.reset(); 656 // UpdateWorkerDependency should be called. 657 EXPECT_EQ(2, s_update_worker_dependency_call_count_); 658 EXPECT_EQ(0U, s_worker_dependency_added_ids_.size()); 659 EXPECT_EQ(1U, s_worker_dependency_removed_ids_.size()); 660 EXPECT_EQ(kProcessIDs[0], s_worker_dependency_removed_ids_[0]); 661 } 662 663 TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest) { 664 // The first renderer host. 665 scoped_ptr<MockRendererProcessHost> renderer_host0( 666 new MockRendererProcessHost(kProcessIDs[0], 667 browser_context_->GetResourceContext(), 668 *partition_.get())); 669 // The second renderer host. 670 scoped_ptr<MockRendererProcessHost> renderer_host1( 671 new MockRendererProcessHost(kProcessIDs[1], 672 browser_context_->GetResourceContext(), 673 *partition_.get())); 674 int worker_route_id; 675 676 // Normal case. 677 { 678 scoped_ptr<MockSharedWorkerConnector> connector0( 679 new MockSharedWorkerConnector(renderer_host0.get())); 680 scoped_ptr<MockSharedWorkerConnector> connector1( 681 new MockSharedWorkerConnector(renderer_host1.get())); 682 connector0->Create("http://example.com/w1.js", 683 "name1", 684 kDocumentIDs[0], 685 kRenderFrameRouteIDs[0]); 686 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 687 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 688 RunAllPendingInMessageLoop(); 689 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 690 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 691 "http://example.com/w1.js", 692 "name1", 693 blink::WebContentSecurityPolicyTypeReport, 694 &worker_route_id); 695 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 696 connector1->Create("http://example.com/w1.js", 697 "name1", 698 kDocumentIDs[1], 699 kRenderFrameRouteIDs[1]); 700 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 701 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 702 RunAllPendingInMessageLoop(); 703 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 704 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 705 } 706 707 // Normal case (URL mismatch). 708 { 709 scoped_ptr<MockSharedWorkerConnector> connector0( 710 new MockSharedWorkerConnector(renderer_host0.get())); 711 scoped_ptr<MockSharedWorkerConnector> connector1( 712 new MockSharedWorkerConnector(renderer_host1.get())); 713 connector0->Create("http://example.com/w2.js", 714 "name2", 715 kDocumentIDs[0], 716 kRenderFrameRouteIDs[0]); 717 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 718 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 719 RunAllPendingInMessageLoop(); 720 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 721 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 722 "http://example.com/w2.js", 723 "name2", 724 blink::WebContentSecurityPolicyTypeReport, 725 &worker_route_id); 726 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 727 connector1->Create("http://example.com/w2x.js", 728 "name2", 729 kDocumentIDs[1], 730 kRenderFrameRouteIDs[1]); 731 EXPECT_EQ(MSG_ROUTING_NONE, connector1->route_id()); 732 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 733 RunAllPendingInMessageLoop(); 734 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 735 } 736 737 // Pending case. 738 { 739 scoped_ptr<MockSharedWorkerConnector> connector0( 740 new MockSharedWorkerConnector(renderer_host0.get())); 741 scoped_ptr<MockSharedWorkerConnector> connector1( 742 new MockSharedWorkerConnector(renderer_host1.get())); 743 connector0->Create("http://example.com/w3.js", 744 "name3", 745 kDocumentIDs[0], 746 kRenderFrameRouteIDs[0]); 747 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 748 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 749 connector1->Create("http://example.com/w3.js", 750 "name3", 751 kDocumentIDs[1], 752 kRenderFrameRouteIDs[1]); 753 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 754 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 755 RunAllPendingInMessageLoop(); 756 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 757 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 758 "http://example.com/w3.js", 759 "name3", 760 blink::WebContentSecurityPolicyTypeReport, 761 &worker_route_id); 762 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 763 EXPECT_EQ(1U, renderer_host1->QueuedMessageCount()); 764 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 765 } 766 767 // Pending case (URL mismatch). 768 { 769 scoped_ptr<MockSharedWorkerConnector> connector0( 770 new MockSharedWorkerConnector(renderer_host0.get())); 771 scoped_ptr<MockSharedWorkerConnector> connector1( 772 new MockSharedWorkerConnector(renderer_host1.get())); 773 connector0->Create("http://example.com/w4.js", 774 "name4", 775 kDocumentIDs[0], 776 kRenderFrameRouteIDs[0]); 777 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 778 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 779 connector1->Create("http://example.com/w4x.js", 780 "name4", 781 kDocumentIDs[1], 782 kRenderFrameRouteIDs[1]); 783 EXPECT_EQ(MSG_ROUTING_NONE, connector1->route_id()); 784 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 785 RunAllPendingInMessageLoop(); 786 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 787 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 788 "http://example.com/w4.js", 789 "name4", 790 blink::WebContentSecurityPolicyTypeReport, 791 &worker_route_id); 792 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 793 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 794 } 795 } 796 797 TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) { 798 // Create three renderer hosts. 799 scoped_ptr<MockRendererProcessHost> renderer_host0( 800 new MockRendererProcessHost(kProcessIDs[0], 801 browser_context_->GetResourceContext(), 802 *partition_.get())); 803 scoped_ptr<MockRendererProcessHost> renderer_host1( 804 new MockRendererProcessHost(kProcessIDs[1], 805 browser_context_->GetResourceContext(), 806 *partition_.get())); 807 scoped_ptr<MockRendererProcessHost> renderer_host2( 808 new MockRendererProcessHost(kProcessIDs[2], 809 browser_context_->GetResourceContext(), 810 *partition_.get())); 811 int worker_route_id; 812 813 scoped_ptr<MockSharedWorkerConnector> connector0( 814 new MockSharedWorkerConnector(renderer_host0.get())); 815 scoped_ptr<MockSharedWorkerConnector> connector1( 816 new MockSharedWorkerConnector(renderer_host1.get())); 817 scoped_ptr<MockSharedWorkerConnector> connector2( 818 new MockSharedWorkerConnector(renderer_host2.get())); 819 connector0->Create("http://example.com/w1.js", 820 "name1", 821 kDocumentIDs[0], 822 kRenderFrameRouteIDs[0]); 823 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 824 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 825 RunAllPendingInMessageLoop(); 826 EXPECT_EQ(2U, renderer_host0->QueuedMessageCount()); 827 CheckWorkerProcessMsgCreateWorker(renderer_host0.get(), 828 "http://example.com/w1.js", 829 "name1", 830 blink::WebContentSecurityPolicyTypeReport, 831 &worker_route_id); 832 CheckViewMsgWorkerCreated(renderer_host0.get(), connector0.get()); 833 renderer_host0->FastShutdownIfPossible(); 834 835 connector1->Create("http://example.com/w1.js", 836 "name1", 837 kDocumentIDs[1], 838 kRenderFrameRouteIDs[1]); 839 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 840 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 841 RunAllPendingInMessageLoop(); 842 EXPECT_EQ(2U, renderer_host1->QueuedMessageCount()); 843 CheckWorkerProcessMsgCreateWorker(renderer_host1.get(), 844 "http://example.com/w1.js", 845 "name1", 846 blink::WebContentSecurityPolicyTypeReport, 847 &worker_route_id); 848 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 849 850 connector2->Create("http://example.com/w1.js", 851 "name1", 852 kDocumentIDs[2], 853 kRenderFrameRouteIDs[2]); 854 EXPECT_NE(MSG_ROUTING_NONE, connector2->route_id()); 855 EXPECT_EQ(0U, renderer_host2->QueuedMessageCount()); 856 RunAllPendingInMessageLoop(); 857 EXPECT_EQ(1U, renderer_host2->QueuedMessageCount()); 858 CheckViewMsgWorkerCreated(renderer_host2.get(), connector2.get()); 859 } 860 861 TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) { 862 // Create three renderer hosts. 863 scoped_ptr<MockRendererProcessHost> renderer_host0( 864 new MockRendererProcessHost(kProcessIDs[0], 865 browser_context_->GetResourceContext(), 866 *partition_.get())); 867 scoped_ptr<MockRendererProcessHost> renderer_host1( 868 new MockRendererProcessHost(kProcessIDs[1], 869 browser_context_->GetResourceContext(), 870 *partition_.get())); 871 scoped_ptr<MockRendererProcessHost> renderer_host2( 872 new MockRendererProcessHost(kProcessIDs[2], 873 browser_context_->GetResourceContext(), 874 *partition_.get())); 875 int worker_route_id; 876 877 scoped_ptr<MockSharedWorkerConnector> connector0( 878 new MockSharedWorkerConnector(renderer_host0.get())); 879 scoped_ptr<MockSharedWorkerConnector> connector1( 880 new MockSharedWorkerConnector(renderer_host1.get())); 881 scoped_ptr<MockSharedWorkerConnector> connector2( 882 new MockSharedWorkerConnector(renderer_host2.get())); 883 connector0->Create("http://example.com/w1.js", 884 "name1", 885 kDocumentIDs[0], 886 kRenderFrameRouteIDs[0]); 887 EXPECT_NE(MSG_ROUTING_NONE, connector0->route_id()); 888 EXPECT_EQ(0U, renderer_host0->QueuedMessageCount()); 889 renderer_host0->FastShutdownIfPossible(); 890 891 connector1->Create("http://example.com/w1.js", 892 "name1", 893 kDocumentIDs[1], 894 kRenderFrameRouteIDs[1]); 895 EXPECT_NE(MSG_ROUTING_NONE, connector1->route_id()); 896 EXPECT_EQ(0U, renderer_host1->QueuedMessageCount()); 897 RunAllPendingInMessageLoop(); 898 EXPECT_EQ(2U, renderer_host1->QueuedMessageCount()); 899 CheckWorkerProcessMsgCreateWorker(renderer_host1.get(), 900 "http://example.com/w1.js", 901 "name1", 902 blink::WebContentSecurityPolicyTypeReport, 903 &worker_route_id); 904 CheckViewMsgWorkerCreated(renderer_host1.get(), connector1.get()); 905 906 connector2->Create("http://example.com/w1.js", 907 "name1", 908 kDocumentIDs[2], 909 kRenderFrameRouteIDs[2]); 910 EXPECT_NE(MSG_ROUTING_NONE, connector2->route_id()); 911 EXPECT_EQ(0U, renderer_host2->QueuedMessageCount()); 912 RunAllPendingInMessageLoop(); 913 EXPECT_EQ(1U, renderer_host2->QueuedMessageCount()); 914 CheckViewMsgWorkerCreated(renderer_host2.get(), connector2.get()); 915 } 916 917 } // namespace content 918