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
29namespace content {
30
31class 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
95int SharedWorkerServiceImplTest::s_update_worker_dependency_call_count_;
96std::vector<int> SharedWorkerServiceImplTest::s_worker_dependency_added_ids_;
97std::vector<int> SharedWorkerServiceImplTest::s_worker_dependency_removed_ids_;
98base::Lock SharedWorkerServiceImplTest::s_lock_;
99std::set<int> SharedWorkerServiceImplTest::s_running_process_id_set_;
100
101namespace {
102
103static const int kProcessIDs[] = {100, 101, 102};
104static const unsigned long long kDocumentIDs[] = {200, 201, 202};
105static const int kRenderFrameRouteIDs[] = {300, 301, 302};
106
107class 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
132class 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
164class 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
226void 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
241void 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
258class 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
321void 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(), &param));
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
337void 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
344void 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
351void 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(), &params));
360  int port_id = params.a;
361  *routing_id = params.b;
362  EXPECT_EQ(expected_sent_message_port_id, port_id);
363}
364
365void 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(), &params));
373  base::string16 data = params.a;
374  EXPECT_EQ(base::ASCIIToUTF16(expected_data), data);
375}
376
377void 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
386TEST_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
482TEST_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
663TEST_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
797TEST_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
861TEST_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