1 // Copyright 2015 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.
5 #include "content/child/service_worker/service_worker_dispatcher.h"
6 #include "content/child/service_worker/web_service_worker_impl.h"
7 #include "content/child/service_worker/web_service_worker_registration_impl.h"
8 #include "content/child/thread_safe_sender.h"
9 #include "content/common/service_worker/service_worker_messages.h"
10 #include "content/common/service_worker/service_worker_types.h"
11 #include "ipc/ipc_sync_message_filter.h"
12 #include "ipc/ipc_test_sink.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 class ServiceWorkerTestSender
: public ThreadSafeSender
{
19 explicit ServiceWorkerTestSender(IPC::TestSink
* ipc_sink
)
20 : ThreadSafeSender(nullptr, nullptr),
21 ipc_sink_(ipc_sink
) {}
23 bool Send(IPC::Message
* message
) override
{
24 return ipc_sink_
->Send(message
);
28 ~ServiceWorkerTestSender() override
{}
30 IPC::TestSink
* ipc_sink_
;
32 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTestSender
);
35 class ServiceWorkerDispatcherTest
: public testing::Test
{
37 ServiceWorkerDispatcherTest() {}
39 void SetUp() override
{
40 sender_
= new ServiceWorkerTestSender(&ipc_sink_
);
41 dispatcher_
.reset(new ServiceWorkerDispatcher(sender_
.get(), nullptr));
44 void CreateObjectInfoAndVersionAttributes(
45 ServiceWorkerRegistrationObjectInfo
* info
,
46 ServiceWorkerVersionAttributes
* attrs
) {
48 info
->registration_id
= 20;
50 attrs
->active
.handle_id
= 100;
51 attrs
->active
.version_id
= 200;
52 attrs
->waiting
.handle_id
= 101;
53 attrs
->waiting
.version_id
= 201;
54 attrs
->installing
.handle_id
= 102;
55 attrs
->installing
.version_id
= 202;
58 WebServiceWorkerRegistrationImpl
* FindOrCreateRegistration(
59 const ServiceWorkerRegistrationObjectInfo
& info
,
60 const ServiceWorkerVersionAttributes
& attrs
) {
61 return dispatcher_
->FindOrCreateRegistration(info
, attrs
);
64 bool ContainsServiceWorker(int handle_id
) {
65 return ContainsKey(dispatcher_
->service_workers_
, handle_id
);
68 bool ContainsRegistration(int registration_handle_id
) {
69 return ContainsKey(dispatcher_
->registrations_
, registration_handle_id
);
72 ServiceWorkerDispatcher
* dispatcher() { return dispatcher_
.get(); }
73 IPC::TestSink
* ipc_sink() { return &ipc_sink_
; }
76 IPC::TestSink ipc_sink_
;
77 scoped_ptr
<ServiceWorkerDispatcher
> dispatcher_
;
78 scoped_refptr
<ServiceWorkerTestSender
> sender_
;
80 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherTest
);
83 // TODO(nhiroki): Add tests for message handlers especially to receive reference
84 // counts like OnAssociateRegistration().
85 TEST_F(ServiceWorkerDispatcherTest
, GetServiceWorker
) {
86 ServiceWorkerRegistrationObjectInfo info
;
87 ServiceWorkerVersionAttributes attrs
;
88 CreateObjectInfoAndVersionAttributes(&info
, &attrs
);
90 // Should return a worker object newly created with incrementing refcount.
91 bool adopt_handle
= false;
92 scoped_ptr
<WebServiceWorkerImpl
> worker(
93 dispatcher()->GetServiceWorker(attrs
.installing
, adopt_handle
));
95 EXPECT_TRUE(ContainsServiceWorker(attrs
.installing
.handle_id
));
96 EXPECT_EQ(1UL, ipc_sink()->message_count());
97 EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID
,
98 ipc_sink()->GetMessageAt(0)->type());
100 ipc_sink()->ClearMessages();
102 // Should return the existing worker object.
103 adopt_handle
= false;
104 WebServiceWorkerImpl
* existing_worker
=
105 dispatcher()->GetServiceWorker(attrs
.installing
, adopt_handle
);
106 EXPECT_EQ(worker
, existing_worker
);
107 EXPECT_EQ(0UL, ipc_sink()->message_count());
109 // Should return the existing worker object with adopting refcount.
112 dispatcher()->GetServiceWorker(attrs
.installing
, adopt_handle
);
113 EXPECT_EQ(worker
, existing_worker
);
114 ASSERT_EQ(1UL, ipc_sink()->message_count());
115 EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID
,
116 ipc_sink()->GetMessageAt(0)->type());
118 ipc_sink()->ClearMessages();
120 // Should return another worker object newly created with adopting refcount.
122 scoped_ptr
<WebServiceWorkerImpl
> another_worker(
123 dispatcher()->GetServiceWorker(attrs
.waiting
, adopt_handle
));
124 EXPECT_NE(worker
.get(), another_worker
.get());
125 EXPECT_TRUE(ContainsServiceWorker(attrs
.waiting
.handle_id
));
126 EXPECT_EQ(0UL, ipc_sink()->message_count());
128 // Should return nullptr when a given object info is invalid.
129 adopt_handle
= false;
130 WebServiceWorkerImpl
* invalid_worker
=
131 dispatcher()->GetServiceWorker(ServiceWorkerObjectInfo(), adopt_handle
);
132 EXPECT_FALSE(invalid_worker
);
133 EXPECT_EQ(0UL, ipc_sink()->message_count());
137 dispatcher()->GetServiceWorker(ServiceWorkerObjectInfo(), adopt_handle
);
138 EXPECT_FALSE(invalid_worker
);
139 EXPECT_EQ(0UL, ipc_sink()->message_count());
142 TEST_F(ServiceWorkerDispatcherTest
, CreateServiceWorkerRegistration
) {
143 ServiceWorkerRegistrationObjectInfo info
;
144 ServiceWorkerVersionAttributes attrs
;
145 CreateObjectInfoAndVersionAttributes(&info
, &attrs
);
147 // Should return a registration object newly created with incrementing
149 bool adopt_handle
= false;
150 scoped_ptr
<WebServiceWorkerRegistrationImpl
> registration(
151 dispatcher()->CreateServiceWorkerRegistration(info
, adopt_handle
));
152 EXPECT_TRUE(registration
);
153 EXPECT_TRUE(ContainsRegistration(info
.handle_id
));
154 ASSERT_EQ(1UL, ipc_sink()->message_count());
155 EXPECT_EQ(ServiceWorkerHostMsg_IncrementRegistrationRefCount::ID
,
156 ipc_sink()->GetMessageAt(0)->type());
158 registration
.reset();
159 EXPECT_FALSE(ContainsRegistration(info
.handle_id
));
160 ipc_sink()->ClearMessages();
162 // Should return another registration object newly created with adopting
165 scoped_ptr
<WebServiceWorkerRegistrationImpl
> another_registration(
166 dispatcher()->CreateServiceWorkerRegistration(info
, adopt_handle
));
167 EXPECT_TRUE(another_registration
);
168 EXPECT_TRUE(ContainsRegistration(info
.handle_id
));
169 EXPECT_EQ(0UL, ipc_sink()->message_count());
171 another_registration
.reset();
172 ipc_sink()->ClearMessages();
174 // should return nullptr when a given object info is invalid.
175 adopt_handle
= false;
176 scoped_ptr
<WebServiceWorkerRegistrationImpl
> invalid_registration(
177 dispatcher()->CreateServiceWorkerRegistration(
178 ServiceWorkerRegistrationObjectInfo(), adopt_handle
));
179 EXPECT_FALSE(invalid_registration
);
180 EXPECT_FALSE(ContainsRegistration(info
.handle_id
));
181 EXPECT_EQ(0UL, ipc_sink()->message_count());
184 invalid_registration
.reset(dispatcher()->CreateServiceWorkerRegistration(
185 ServiceWorkerRegistrationObjectInfo(), adopt_handle
));
186 EXPECT_FALSE(invalid_registration
);
187 EXPECT_FALSE(ContainsRegistration(info
.handle_id
));
188 EXPECT_EQ(0UL, ipc_sink()->message_count());
191 TEST_F(ServiceWorkerDispatcherTest
, FindOrCreateRegistration
) {
192 ServiceWorkerRegistrationObjectInfo info
;
193 ServiceWorkerVersionAttributes attrs
;
194 CreateObjectInfoAndVersionAttributes(&info
, &attrs
);
196 // Should return a registration object newly created with adopting refcounts.
197 scoped_ptr
<WebServiceWorkerRegistrationImpl
> registration(
198 FindOrCreateRegistration(info
, attrs
));
199 EXPECT_TRUE(registration
);
200 EXPECT_EQ(info
.registration_id
, registration
->registration_id());
201 EXPECT_EQ(0UL, ipc_sink()->message_count());
203 // Should return the existing registration object with adopting refcounts.
204 WebServiceWorkerRegistrationImpl
* existing_registration
=
205 FindOrCreateRegistration(info
, attrs
);
206 EXPECT_EQ(registration
, existing_registration
);
207 ASSERT_EQ(4UL, ipc_sink()->message_count());
208 EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID
,
209 ipc_sink()->GetMessageAt(0)->type());
210 EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID
,
211 ipc_sink()->GetMessageAt(1)->type());
212 EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID
,
213 ipc_sink()->GetMessageAt(2)->type());
214 EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID
,
215 ipc_sink()->GetMessageAt(3)->type());
218 } // namespace content